Linux C ++编译器(和链接器)如何决定将typeinfo放在何处?

时间:2011-05-23 12:47:41

标签: c++ linux compiler-construction linker rtti

我在一个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符号将具有模糊的链接。

4 个答案:

答案 0 :(得分:3)

G ++可能将类的typeinfo定义为弱 符号,在每个需要它的目标文件中。其中一个对象 libdef中的文件需要它,因为它是vtable的一部分 由构造函数安装。和其中一个目标文件 由于libdyndynamic_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?