You need to enable JavaScript to run this app. C++类编译为共享库时,已实现的虚函数为何会引发type_info依赖?
优惠活动
大模型
产品
解决方案
定价
更多

C++类编译为共享库时,已实现的虚函数为何会引发type_info依赖?

两类CXXABI符号依赖的底层触发机制

先解码你看到的两个未定义符号

对nm输出的两个符号做名字修饰逆向(demangle)后可以得到:

  • _ZTVN10__cxxabiv117__class_type_infoE@@CXXABI_1.3 对应 __cxxabiv1::__class_type_info类的虚表,是Itanium C++ ABI规定的、用于描述无基类/无多继承结构多态类的RTTI元信息对象的类型
  • _ZTVN10__cxxabiv120__si_class_type_infoE@@CXXABI_1.3 对应 __cxxabiv1::__si_class_type_info类的虚表,是用于描述单public继承自多态基类的多态类的RTTI元信息对象的类型

这两个类的实现完全由系统自带的C标准运行时(libstdc/libc++)提供,不属于用户编写代码的职责范围。

多态类的强制ABI约束

g遵循的Itanium C ABI对任何带虚函数的多态类有不可绕过的强制要求:只要触发了类的虚表生成流程,就必须同步为该类生成对应的RTTI描述对象,核心原因是虚表的固定内存布局,第一个槽位就必须存放一个指向本类RTTI对象的指针。哪怕用户的代码从头到尾没有用过typeid、dynamic_cast这类RTTI接口,这个约束也不会失效。

这里有个常见的认知误区:这类符号依赖和“某个虚函数没有实现”没有直接因果关系。通常虚函数缺失实现触发的未定义符号,是用户自己定义的虚函数入口地址的缺失,和上述两个RTTI核心类的虚表完全是两回事。

对应你代码的完整触发链路

逐环节拆解编译流程即可看到依赖的生成逻辑:

  1. 代码中定义的Foo是无基类的多态抽象类,带有纯虚函数do_something
  2. 代码中定义的Bar以单public方式继承自Foo,完整实现了do_something接口,是可实例化的多态具体类
  3. 全局作用域定义的Bar bar;实例,会强制编译器生成Bar的全局对象构造函数。构造多态对象时,必须将对象内存头部的vptr指针指向对应类的虚表,这就直接触发了两个类的虚表生成流程:
    • 生成Foo的虚表时,按照布局要求需要填入指向Foo类RTTI对象的指针。Foo作为无基类的多态类,对应的RTTI对象类型是__class_type_info;编译器生成这个全局RTTI对象时,因为__class_type_info本身也是多态类(带有类型比较、判定等虚函数接口),必须引用它自身的虚表才能完成对象构造,因此产生对第一个未定义符号的依赖
    • 生成Bar的虚表时,同理需要填入指向Bar类RTTI对象的指针。Bar作为单继承自多态基类的具体类,对应的RTTI对象类型是__si_class_type_info;编译器生成这个全局RTTI对象时,必须引用__si_class_type_info自身的虚表,因此产生对第二个未定义符号的依赖

为什么这些符号是未定义(U)状态

这是共享库的正常设计行为:用户编写的代码只是需要实例化两个属于C++ ABI核心的RTTI类型,这两个类型的虚表实现由系统安装的libstdc++.so动态提供。生成共享库时,链接器只会记录“运行时需要从libstdc解析这两个虚表地址”的依赖项,不会把libstdc的实现打包进自研的foobar.so。这种未定义状态完全符合动态链接的预期,不是编译错误。

-fno-rtti消除依赖的原理

开启-fno-rtti选项后,编译器会调整多态类的虚表布局,将原本要放置RTTI对象指针的槽位直接置为空值,完全不为多态类生成对应的RTTI描述对象。既然不会生成这些RTTI实例,自然也就不需要引用底层RTTI核心类的虚表符号了。

补充:什么时候这类符号不会出现

按照ABI的规则,多态类的虚表和RTTI对象,默认只在**定义了类的关键函数(key function)**的编译单元生成。如果只是写了类定义,没有触发以下任意场景,就不会拉取这类符号:

  • 没有在全局作用域定义类的实例(触发构造函数生成流程)
  • 没有定义类的非内联关键虚函数
  • 没有在代码中通过typeid、dynamic_cast显式引用类的RTTI信息

内容的提问来源于stack exchange,提问作者Peter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.27 19:24:00