我在一个h文件中定义了一个类,并在一个lib中实现了一个cpp(我们称之为libdef)。
我还有另外两个包含此h文件的cpp文件的库。其中一个对这个类做了dynamic_cast()(我们称之为libdyn),另一个为这个类做了新的(我们称之为libnew)。
似乎在其中一个库中有类型的typeinfo,但在另一个库中没有:
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
正如您所看到的,libdef和libnew都使用libdef中的typeinfo,但libdyn使用自己的typeinfo。这是为什么?编译器/链接器如何决定是将typeinfo放在一个lib中还是从另一个lib引用它?
我应该注意libnew和libdyn都是用-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
经过一些检查后,这取决于lib的cpp文件是否“看到”虚拟方法定义。
此代码不会导致库中的typeinfo符号:
class SomeClass { public: SomeClass(); virtual void func(); };
此代码将在库中生成一个typeinfo符号:
class SomeClass { public: SomeClass() {} virtual void func() {} };
当存在时,typeinfo符号将具有模糊的链接。
答案 0 :(得分:3)
G ++可能将类的typeinfo定义为弱
符号,在每个需要它的目标文件中。其中一个对象
libdef
中的文件需要它,因为它是vtable
的一部分
由构造函数安装。和其中一个目标文件
由于libdyn
,dynamic_cast
需要它。我摔倒
libnew
确实是新的,但它可能不需要它
(除非构造函数是内联的)。无论如何,如果它真的
是一个弱的符号,只有一个定义
并入最终的或可执行的;哪一个是
未指定(但我怀疑它是第一个链接器
遭遇 - 这与你所看到的相对应。)
大部分时间都不重要。 (例外是如果
您使用dlopen
致电RTLD_LOCAL
;这样做,并且
dynamic_cast
如果在.so
中执行,可能会失败
除了具有对象构造函数的那个。)
答案 1 :(得分:2)
正如其他人所提到的,这取决于C ++的实现。但here描述了g ++是如何做到的。
简单地说,如果可能,g ++在翻译单元中定义类vtable和type_info,它定义了类的第一个非内联虚拟成员。
答案 2 :(得分:0)
我认为这将是编译器的实现细节。
通常(因为虚拟表本身是一个实现细节),virtual table
存储指向type info
的指针,我认为存储typeinfo的地方是编译器的实现细节。很可能它将typeinfo
存储在声明该类的so
中。
答案 3 :(得分:0)
我不知道您的编译器和链接器的实现细节,但是它可能足够聪明,不包含不需要它的typeinfo?