How does the Linux C++ compiler (and linker) decide where to put typeinfo?
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
typeinf开发者_运维百科o 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 libdef
needs it, because it's part of the vtable
installed by the constructor. And one of the object files in
libdyn
needs it, because of the dynamic_cast
. If all
libnew
does 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 dlopen
with RTLD_LOCAL
; do this, and
dynamic_cast
is likely to fail if it executed in an .so
other than the one with the object's constructor.)
As others have mentioned, this depends on the C++ implementation. But here is a description of how g++ does it.
Briefly, when possible, g++ defines the class vtable and type_info in the translation unit which defines the first non-inline virtual member of the class.
I think it would be an implementation detail of compiler.
Usually(since virtual table itself is a implementation detail), the virtual table
stores a pointer to the type info
and I think where the typeinfo is stored is implementation detail of compiler. Most probably it stores the typeinfo
in the so
which declares the class.
I don't know the implementation details of your compiler and linker, but perhaps it's smart enough not to include the typeinfo where it isn't needed?
精彩评论