Skip to content
Advertisement

Why doesn’t defining `__cxa_throw` cause a link error?

Why doesn’t the following C++ program have a link conflict with the system-provided __cxa_throw ?

#include <cstring>

void __cxa_throw(void *, void *, void (*)(void *)) {
    std::puts("bad luck");
}

int main() {
    throw 13;
}

Is there something magical about that symbol? For a normal function this would be an ODR violation wouldn’t it?

Advertisement

Answer

As @Igor pointed out, you need to add extern "C" to prevent name mangling.

But the cause why it works is because the symbol is most likely defined as weak. This means that if you redefine it, the linker will use your version instead of the standard’s library.

Gcc’s source code confirms they define it as weak. I am unsure about the reason, perhaps some internal compatiblity with shared libraries and such… Actually there is a comment right above the definition I somehow missed:

77 /* Everything from libstdc++ is weak, to avoid requiring that library
   to be linked into plain C applications using libitm.so.  */

So that’s the reason.

It goes without saying that it is really terrible idea to do this, more even without proper documentation on what other functions expect __cxa_throw to do.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement