抛出'std :: system_error'实例后终止调用 [英] terminate called after throwing an instance of 'std::system_error'

查看:118
本文介绍了抛出'std :: system_error'实例后终止调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

抛出'std :: system_error'实例后调用

  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 *) &GTHR_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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆