https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70503
Bug ID: 70503 Summary: extern "C" functions in src/c++11/thread.cc are global in libstdc++.a Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- In src/c++11/thread.cc we have: namespace std { namespace { extern "C" void* execute_native_thread_routine(void*) { // ... } #if _GLIBCXX_THREAD_ABI_COMPAT extern "C" void* execute_native_thread_routine_compat(void* __p) { // ... } #endif } // ... I was under the mistaken impression that the unnamed namespace meant those functions got internal linkage, but as PR 70476 points out, that's not true. This means the functions are global symbols in the static library (they're not exported from the shared library because the linker script makes everything internal by default and only selected symbols are exported). The following program should fail to link, but with -static it finds the function in libstdc++.a and so crashes: #include <iostream> extern "C" long execute_native_thread_routine(long i, long j); int main() { std::cout << execute_native_thread_routine(0, 0); } Variations can be produced with different link order that will produce a multiple definition error, which happens with the RHEL devtoolset. This bug has been present for some time, but is made worse in GCC 6 because I renamed execute_native_thread_routine to execute_native_thread_routine_compat and added a different function called execute_native_thread_routine. This means we now have an additional global function in libstdc++.a, and the behaviour of the original one changed.