Why does GCC's threading standard library implementation throw exceptions if you don't include pthread?

a 夏天 提交于 2020-07-19 03:43:11

问题


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;
}

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)

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.


回答1:


The reason for this is that libstdc++ uses the so called weak references.

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);

where gthread_once is:

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

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

Now let's take a look at 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 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:

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.


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



来源:https://stackoverflow.com/questions/62308664/why-does-gccs-threading-standard-library-implementation-throw-exceptions-if-you

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!