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 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.