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

我有一个在一个h文件中定义的类,并在一个lib(我们称之为libdef)的cpp中实现.

我还有另外两个包含此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符号将具有模糊的链接.

解决方法:

G可能将类的typeinfo定义为弱
符号,在每个需要它的目标文件中.其中一个对象
libdef中的文件需要它,因为它是vtable的一部分
由构造函数安装.和其中一个目标文件
由于dynamic_cast,libdyn需要它.我摔倒
libnew确实是一个新的,但它可能不需要它
(除非构造函数是内联的).无论如何,如果它真的
是一个弱的符号,只有一个定义
并入最终的或可执行的;哪一个是
未指定(但我怀疑它是第一个链接器
遇到 – 这对应于你所看到的).

大部分时间都不重要. (例外是如果
你用RTLD_LOCAL调用dlopen;这样做,并且
如果在.so中执行,dynamic_cast可能会失败
除了具有对象构造函数的那个​​.)

上一篇:C/C++ RTTI


下一篇:C++ RTTI