抛出'std :: system_error'实例后终止调用 [英] terminate called after throwing an instance of 'std::system_error'
问题描述
当我在Linux版本2.6.36中使用 std :: call_once
时,会出错:
terminatewhat():未知错误-1中止
编译命令:
mipsel-buildroot-linux-uclibc-g ++ callonce.cpp -o callonce -static -lpthread
我的代码:
#include< iostream>#include< mutex>使用命名空间std;int main(){cout<<"Hello world"<<std :: endl;静态的one_flag;call_once(of,[] {});返回0;}
静态链接和动态链接之间存在主要区别.前者仅链接来自 .a
的目标文件,该文件解析当前未解析的符号,而共享库 .so
则完整链接,无论如何(除非 -Wl,-按需使用
链接器选项).
碰巧的是,GNU C ++标准库 std :: call_once
通过检查是否可以解析 pthread_create
来检查应用程序是否是多线程的.由于您的代码不会使用非默认构造函数调用 pthread_create
或 std :: thread
,因此静态链接 -pthread
不会链接 pthread_create
,因此 std :: call_once
失败.通过调用 __ gthread_active_p
函数完成检查:
/*对于要成为多线程的程序,它唯一必须要做的就是正在使用的是pthread_create.但是,可能还有其他图书馆截取带有自己定义的pthread_create来包装pthread出于某些目的的功能.在这些情况下,pthread_create被定义不一定意味着libpthread实际上已链接在.对于GNU C库,我们可以使用一个已知的内部名称.这总是可以在ABI中使用,但没有其他库可以定义它.那是理想的做法是,因为任何公共pthread函数都可能像pthread_create可能是.__pthread_key_create是一个内部"对象.实施符号,但它是公共导出的ABI的一部分.还,它是静态libpthread.a始终链接到的符号之一每当使用pthread_create时,都不会出现错误的危险在任何静态链接的多线程程序中均产生否定结果.对于其他人,我们选择pthread_cancel作为似乎不太可能的函数由拦截器库重新定义.仿生(Android)C库不提供pthread_cancel,因此我们使用pthread_create在那里(拦截器库丢失).*/#ifdef __GLIBC____gthrw2(__ gthrw _(__ pthread_key_create),__pthread_key_create,pthread_key_create)#定义GTHR_ACTIVE_PROXY __gthrw _(__ pthread_key_create)#elif定义(__BIONIC__)#定义GTHR_ACTIVE_PROXY __gthrw_(pthread_create)#别的#定义GTHR_ACTIVE_PROXY __gthrw_(pthread_cancel)#万一静态内联int__gthread_active_p(无效){静态void * const __gthread_active_ptr= __extension__(void *)& GTHR_ACTIVE_PROXY;返回__gthread_active_ptr!= 0;}
一种解决方法是 #include< pthread.h>
并在 main
函数的顶部添加一两行:
static_cast< void>(pthread_create);static_cast< void>(pthread_cancel);
这会导致对 pthread_create
和 pthread_cancel
的未定义引用,并使这些函数中的 -static -pthread
链接从静态库链接到您的应用程序,这使得 __ gthread_active_p
函数返回 1
,进而使 std :: call_once
正常工作.
另一种解决方法是使用 -Wl,-undefined = pthread_create,-undefined = pthread_cancel
链接器命令行选项,而无需更改源代码.
请注意,在现代世界中,使用 -lpthread
既不必要也不充分./p>
When i use std::call_once
in Linux version 2.6.36,it makes an error:
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted
Compile command:
mipsel-buildroot-linux-uclibc-g++ callonce.cpp -o callonce -static -lpthread
my code:
#include <iostream>
#include <mutex>
using namespace std;
int main()
{
cout << "Hello world" << std::endl;
static once_flag of;
call_once(of,[]{});
return 0;
}
There is a major difference between linking statically and dynamically. The former only links in object files from .a
which resolve currently unresolved symbols, whereas a shared library .so
is linked in in its entirety regardless (unless -Wl,--as-needed
linker option is used).
It so happens, that GNU C++ standard library std::call_once
checks whether the application is multi-threaded by checking whether pthread_create
can be resolved. Since your code doesn't invoke pthread_create
or std::thread
with non-default constructor, statically linking -pthread
doesn't link in pthread_create
, and hence std::call_once
fails. The check is done by invoking __gthread_active_p
function:
/* For a program to be multi-threaded the only thing that it certainly must
be using is pthread_create. However, there may be other libraries that
intercept pthread_create with their own definitions to wrap pthreads
functionality for some purpose. In those cases, pthread_create being
defined might not necessarily mean that libpthread is actually linked
in.
For the GNU C library, we can use a known internal name. This is always
available in the ABI, but no other library would define it. That is
ideal, since any public pthread function might be intercepted just as
pthread_create might be. __pthread_key_create is an "internal"
implementation symbol, but it is part of the public exported ABI. Also,
it's among the symbols that the static libpthread.a always links in
whenever pthread_create is used, so there is no danger of a false
negative result in any statically-linked, multi-threaded program.
For others, we choose pthread_cancel as a function that seems unlikely
to be redefined by an interceptor library. The bionic (Android) C
library does not provide pthread_cancel, so we do use pthread_create
there (and interceptor libraries lose). */
#ifdef __GLIBC__
__gthrw2(__gthrw_(__pthread_key_create),
__pthread_key_create,
pthread_key_create)
# define GTHR_ACTIVE_PROXY __gthrw_(__pthread_key_create)
#elif defined (__BIONIC__)
# define GTHR_ACTIVE_PROXY __gthrw_(pthread_create)
#else
# define GTHR_ACTIVE_PROXY __gthrw_(pthread_cancel)
#endif
static inline int
__gthread_active_p (void)
{
static void *const __gthread_active_ptr
= __extension__ (void *) >HR_ACTIVE_PROXY;
return __gthread_active_ptr != 0;
}
One fix is to #include <pthread.h>
and add a line or two to the top of your main
function:
static_cast<void>(pthread_create);
static_cast<void>(pthread_cancel);
That causes undefined references to pthread_create
and pthread_cancel
and makes -static -pthread
link in these functions from the static library into your application, which makes __gthread_active_p
function return 1
and, in turn, enables std::call_once
to work.
Another fix is to use -Wl,--undefined=pthread_create,--undefined=pthread_cancel
linker command line option, which doesn't require source code changes.
Note that in the modern world using -lpthread
is neither necessary nor sufficient.
这篇关于抛出'std :: system_error'实例后终止调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!