I have a class defined in one h file and implemented in a cpp that is part of one lib (we’ll call it libdef).
I have two other libs that have cpp files that include this h file. One of them does dynamic_cast() to this class (we’ll call it libdyn) and the other does new for this class (we’ll call it libnew).
It seems that in one of these libs there’s typeinfo for the type but not in the other:
user@machine> ld --cref libdef.so | grep -E "typeinfo for MyClass"
ld: warning: cannot find entry symbol _start; not setting start address
typeinfo for MyClass libdef.so
user@machine> ld --cref libnew.so | grep -E "typeinfo for MyClass"
ld: warning: cannot find entry symbol _start; not setting start address
typeinfo for MyClass libdef.so
user@machine> ld --cref libdyn.so | grep -E "typeinfo for MyClass"
ld: warning: cannot find entry symbol _start; not setting start address
typeinfo for MyClass libdyn.so
As you can see both libdef and libnew use the typeinfo from libdef, but libdyn uses its own typeinfo. Why is that? How does the compiler/linker decide whether to put the typeinfo in one lib or reference it from the other?
I should note that both libnew and libdyn are built with -llibdef.
user@machine> icpc -V
Intel(R) C++ Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.0.084 Build 20101006
Copyright (C) 1985-2010 Intel Corporation. All rights reserved.
user@machine> ld -V
GNU ld version 2.17.50.0.6-14.el5 20061020
Supported emulations:
elf_x86_64
elf_i386
i386linux
After some checks I did, it depends on whether the cpp files of the lib “see” a virtual method definition or not.
This code will not result in the typeinfo symbol being in the library:
class SomeClass { public: SomeClass(); virtual void func(); };
This code will produce a typeinfo symbol in the library:
class SomeClass { public: SomeClass() {} virtual void func() {} };
When present, the typeinfo symbol will have vague linkage.
G++ probably defines the typeinfo for the class as a weak
symbol, in every object file that needs it. One of the object
files in
libdefneeds it, because it’s part of thevtableinstalled by the constructor. And one of the object files in
libdynneeds it, because of thedynamic_cast. If alllibnewdoes is a new, however, it likely wouldn’t need it(unless the constructor is inline). At any rate, if it really
is a weak symbol, only one of the definitions will be
incorporated into the final so or executable; which one is
unspecified (but I suspect that it is the first one the linker
encounters—which corresponds to what you’re seeing).
None of which matters most of the time. (The exception is if
you’re calling
dlopenwithRTLD_LOCAL; do this, anddynamic_castis likely to fail if it executed in an.soother than the one with the object’s constructor.)