luy*_*uan 5 c++ multithreading libstdc++ c++11
当我std::call_once在 Linux 2.6.36 版中使用时,出现错误:
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted
Run Code Online (Sandbox Code Playgroud)
编译命令:
mipsel-buildroot-linux-uclibc-g++ callonce.cpp -o callonce -static -lpthread
Run Code Online (Sandbox Code Playgroud)
我的代码:
#include <iostream>
#include <mutex>
using namespace std;
int main()
{
cout << "Hello world" << std::endl;
static once_flag of;
call_once(of,[]{});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
静态链接和动态链接之间存在重大差异。前者只在目标文件中链接,.a从中解析当前未解析的符号,而共享库.so则是整体-Wl,--as-needed链接的(除非使用链接器选项)。
碰巧的是,GNU C++ 标准库std::call_once通过检查是否pthread_create可以解析来检查应用程序是否是多线程的。由于您的代码不调用pthread_create或std::thread使用非默认构造函数,静态链接-pthread不会链接 in pthread_create,因此std::call_once失败。检查是通过调用__gthread_active_p函数完成的:
/* 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;
}
Run Code Online (Sandbox Code Playgroud)
一种解决方法是#include <pthread.h>在main函数顶部添加一两行:
static_cast<void>(pthread_create);
static_cast<void>(pthread_cancel);
Run Code Online (Sandbox Code Playgroud)
这会导致对pthread_create和 的未定义引用pthread_cancel,并使-static -pthread这些函数从静态库链接到您的应用程序,从而使__gthread_active_p函数返回,进而使函数1能够std::call_once工作。
另一个修复是使用-Wl,--undefined=pthread_create,--undefined=pthread_cancel链接器命令行选项,它不需要更改源代码。
需要注意的是在现代世界中使用-lpthread既不必要也不充分。
| 归档时间: |
|
| 查看次数: |
689 次 |
| 最近记录: |