提问者:小点点

定义的虚函数导致type_info依赖


我有以下文件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进行编译来规避这个问题,但我正在尝试理解这种行为。


共1个答案

匿名用户

您将看到这些libstdc++符号的一些依赖关系,只要:

  • 构造函数ODR用于动态类类型(具有虚函数或虚基)。
  • 任何操作数为类类型或类类型表达式的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”符号。