定义的虚函数导致 type_info 依赖

Defined virtual functions cause type_info dependence

我有以下文件 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++ 符号的一些依赖:

  • 一个构造函数被 odr 用于动态 class 类型(具有虚函数或虚基)。
  • 任何操作数为 class 类型的 typeid 表达式或 class 类型的表达式都会被编译(因此不在 decltype 中,在内联函数中永远不会二手等)
  • 任何具有 class 类型操作数的 throw 表达式都会被编译。

请注意,后两者根本不需要动态 class 类型。它们对其他类型的等价物也会导致对其他 libstdc++ type_info 相关符号的依赖。

这是继 Itanium ABI (section 2.9.4 RTTI Layout) 之后 type_info 继承信息存储方式的结果。任何 class 类型的 type_info 对象实际上具有继承 std::type_info 的最派生类型 __cxxabiv1::__class_type_info__cxxabiv1::__si_class_type_info。但由于 std::type_info 是动态的,因此 __class_type_info__si_class_type_info 也是动态的。这意味着创建的那些类型的对象必须有 vptrs。这些 vptrs 必须包含一个指向 std::type_info 对象的指针,表示实现类型 __class_type_info__si_class_type_info 本身。显然,这些对象是在没有按需链接的情况下创建的,但每个对象都包含一个指向要由 std::type_info::name() 返回的名称字符串的指针,它们是您看到的从 libstdc++ 链接的实际“_ZTVN”符号。