我有以下文件foobar.cc
:
struct Foo
{
virtual int do_something() const = 0;
};
struct Bar : public Foo
{
virtual int do_something() const override
{ return 1; }
};
Bar bar;
当我试图用它构建一个共享对象时,如下所示:
g++ -shared -fPIC foobar.cc -o foobar.so
nm foobar.so
输出行:
U _ZTVN10__cxxabiv117__class_type_infoE@@CXXABI_1.3
U _ZTVN10__cxxabiv120__si_class_type_infoE@@CXXABI_1.3
但为什么?难道只有当其中一个虚函数不是纯粹的或者没有定义时,才应该这样吗?我知道我可以通过使用fno-rtti
进行编译来规避这个问题,但我正在尝试理解这种行为。
您将看到这些libstdc++符号的一些依赖关系,只要:
TypeID
表达式都将被编译(因此不在DeclType
中,也不在从未使用过的内联函数中,等等)throw
表达式。注意后两者根本不需要动态类类型。其他类型的等价物也会导致对其他libstdc++type_info
相关符号的依赖。
这是按照Itanium ABI(第2.9.4节RTTI布局)存储type_info
继承信息方式的结果。任何类类型的type_info
对象实际上都具有最派生的类型__cxxabiv1:::_class_type_info
或_cxxabiv1:::_si_class_type_info
,它们继承std::type_info
。但是,由于std::type_info
是动态的,__class_type_info
和__si_class_type_info
也是动态的。这意味着创建的这些类型的对象必须具有vptr。这些VPTR必须包含指向std::type_info
对象的指针,这些对象表示实现类型__class_type_info
和__si_class_type_info
本身。显然,这些对象是在没有按需链接的情况下创建的,但每个对象都包含一个指向由std::type_info::name()
返回的名称字符串的指针,这些字符串是您看到的从libstdc++链接的实际“_ztvn
”符号。