gpt4 book ai didi

c++ - 抛出 'std::system_error'实例后终止调用

转载 作者:行者123 更新时间:2023-12-03 10:05:05 25 4
gpt4 key购买 nike

当我在Linux版本2.6.36中使用std::call_once时,出现错误:

terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted
编译命令:
mipsel-buildroot-linux-uclibc-g++ callonce.cpp -o callonce -static -lpthread
我的代码:
#include <iostream>
#include <mutex>
using namespace std;
int main()
{
cout << "Hello world" << std::endl;
static once_flag of;
call_once(of,[]{});

return 0;
}

最佳答案

静态链接和动态链接之间存在主要区别。前者仅链接来自.a的目标文件中的链接,这些文件解析了当前无法解析的符号,而共享库.so则完整链接了(除非使用-Wl,--as-needed链接器选项)。
碰巧的是,GNU C++标准库std::call_once通过检查pthread_create是否可以解析来检查应用程序是否是多线程的。由于您的代码不会使用非默认构造函数调用pthread_createstd::thread,因此静态链接-pthread不会在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 *) &GTHR_ACTIVE_PROXY;
return __gthread_active_ptr != 0;
}

一种解决方法是 #include <pthread.h>,并在 main函数的顶部添加一行或两行:
static_cast<void>(pthread_create);
static_cast<void>(pthread_cancel);
这将导致对 pthread_createpthread_cancel的 undefined reference ,并使这些函数中的 -static -pthread链接从静态库进入您的应用程序,这使 __gthread_active_p函数返回 1,进而使 std::call_once起作用。

另一个解决方法是使用 -Wl,--undefined=pthread_create,--undefined=pthread_cancel链接器命令行选项,该选项不需要更改源代码。

请注意,在现代世界中使用 -lpthread is neither necessary nor sufficient

关于c++ - 抛出 'std::system_error'实例后终止调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65335620/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com