问题
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 *)>hrw_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, >hrw_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 interceptpthread_create
with their own definitions to wrappthreads
functionality for some purpose. In those cases,pthread_create
being defined might not necessarily mean thatlibpthread
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 aspthread_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 staticlibpthread.a
always links in wheneverpthread_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