定义的虚函数导致 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
”符号。
我有以下文件 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
”符号。