如果不包含pthread,为什么GCC的线程标准库实现会引发异常? [英] Why does GCC's threading standard library implementation throw exceptions if you don't include pthread?

查看:160
本文介绍了如果不包含pthread,为什么GCC的线程标准库实现会引发异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我编写使用例如 std :: promise 的代码,并且在GCC中不包含PThread库时,会抛出异常,而不是链接器错误。例如:

When I write code that uses, for example, std::promise, and I don't include the PThread library in GCC, I get an exception thrown rather than a linker error. For example:

void product(std::promise<int> intPromise, int a, int b)
{
    intPromise.set_value(a * b);
}
int main()
{
    int a = 20;
    int b = 10;
    std::promise<int> prodPromise;
    std::future<int> prodResult = prodPromise.get_future();
    product(std::move(prodPromise), a, b);
    std::cout << "20*10= " << prodResult.get() << std::endl;
}

如果我在不使用 -pthread的情况下编译此代码,将引发以下异常:

If I compile this code without -pthread, the following exception is thrown:

terminate called after throwing an instance of 'std::system_error'
  what():  Unknown error -1
Aborted (core dumped)

如果 std :: promise 在内部使用 pthread 库,如果我不给它,它应该抛出正确的链接错误 -pthread 命令行选项,用于 g ++ 。但是它编译时没有任何错误,并且在运行时遇到了上述问题。

If std::promise using the pthread library internally, then it should throw linkage error right if I don't give the -pthread commandline option to g++. But it's compiling without any errors and while running I am getting the above issue.

推荐答案

原因是 libstdc ++ 使用所谓的弱引用

我们可以轻松地跟踪为什么您的特定代码示例引发异常。 set_value()调用 std :: call_once 。该函数在其实现中具有该行 *

We can easily trace why your particular code example throws an exception. set_value() calls std::call_once. That function in its implementation has the line*:

int e = gthread_once(&once.M_once, &once_proxy);

其中 gthread_once

static inline int gthread_once(gthread_once_t *once, void (*func)(void))
{
  if (gthread_active_p())
    return ...
  else
    return -1;
}

gthread_active_p 返回 false ,这就是为什么 gthread_once 返回 -1 的原因

gthread_active_p returns false, that's why gthread_once returns -1, which is mentioned in the exception string.

现在让我们看看 gthread_active_p

static __typeof(pthread_key_create) gthrw_pthread_key_create
    __attribute__ ((weakref("__pthread_key_create")));

static inline int gthread_active_p(void)
{
  static void *const gthread_active_ptr = (void *)&gthrw_pthread_key_create;
  return gthread_active_ptr != 0;
}

gthrw_pthread_key_create __ pthread_key_create 的引用不足。如果链接器未找到符号 __ pthread_key_create ,则& gthrw_pthread_key_create 将为空指针,如果<$ c找到$ c> __ pthread_key_create , gthrw_pthread_key_create 将为其别名。 __ pthread_key_create pthreads 库导出。

gthrw_pthread_key_create is a weak reference to __pthread_key_create. If there is no symbol __pthread_key_create found by the linker, &gthrw_pthread_key_create will be a null pointer, if __pthread_key_create is found, gthrw_pthread_key_create will be an alias for it. __pthread_key_create is exported by the pthreads library.

标准库源代码也包含以下注释:

The standard library source code also contains the following comment:


要使程序成为多线程程序,它肯定必须使用的唯一内容是 pthread_create 。但是,可能还有其他一些库使用自己的定义拦截 pthread_create 来包装 pthreads 功能。在这些情况下,定义 pthread_create 不一定意味着实际上已链接 libpthread

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.

对于GNU C库,我们可以使用一个已知的内部名称。它在ABI中始终可用,但是没有其他库可以定义它。这是理想的,因为任何公共 pthread 函数都可能会被拦截,就像 pthread_create可能是一样。 __ pthread_key_create 是一个内部实现符号,但它是公共导出的ABI的一部分。此外,在使用 pthread_create 时,静态 libpthread.a 总是会链接到这些符号中,因此没有在任何静态链接的多线程程序中都有错误的否定结果的危险。

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.






* 删除了一些下划线,并扩展了宏以提高可读性。


* Some underscores are removed and macros are expanded to improve readability.

这篇关于如果不包含pthread,为什么GCC的线程标准库实现会引发异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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