使用-nostdlib实现C++异常时出现int类型信息未定义引用错误
typeinfo for int问题 问题背景
我在做一个迷你标准库替代项目,尝试实现基础异常机制,写了一段极简代码:
int memory[4]; void* __cxa_allocate_exception(long unsigned int thrown_size) throw() { return memory; } void __cxa_free_exception(void * thrown_exception) throw() { } void __cxa_throw(void* thrown_exception, void * tinfo, void (*dest)(void*)) { while(1){}; } extern "C" void _start() { throw 2; }
用-nostdlib编译时,出现链接错误:
undefined reference to `typeinfo for int'
查看编译器生成的汇编代码,能看到这一行:
mov esi, OFFSET FLAT:typeinfo for int
核心疑问
typeinfo for int到底是什么?它不是带空格的常规函数/变量名,完全搞不懂它的本质。- 尝试添加
-nostdlib -frtti -static-libstdc++编译选项后还是报错,这是为什么?
一、typeinfo for int的本质
typeinfo for int是GCC下C++ RTTI(运行时类型信息)机制的产物——它是代表int类型的**std::type_info实例的链接符号名**。
编译器会为每个需要RTTI支持的类型生成一个std::type_info对象,用来存储类型的名称、哈希值等信息。GCC对这个对象的符号命名规则就是typeinfo for [类型名],这里的空格是符号名的合法组成部分,链接器会把它当作一个整体符号处理。
当你抛出int类型异常时,编译器需要把该类型的std::type_info指针作为第二个参数传给__cxa_throw函数(也就是汇编里通过esi寄存器传递的内容),所以会在代码里引用这个符号,而你的迷你库没实现它,就会报链接错误。
二、为什么加-static-libstdc++仍报错
-nostdlib选项的作用是完全禁用所有标准库的链接,包括libstdc++。即使你加了-static-libstdc++,-nostdlib的优先级更高,编译器不会主动链接libstdc++里的类型信息对象。
另外,libstdc++的typeinfo依赖完整的标准库初始化流程,而你自定义的_start函数没有做这些初始化工作,就算强行链接也会出现其他问题。
三、可行的解决思路
根据你的迷你标准库项目需求,有两个方向可选:
1. 禁用RTTI
编译时添加-fno-rtti选项,这样编译器不会生成任何与RTTI相关的代码,自然也不会引用typeinfo符号。缺点是后续无法使用dynamic_cast等依赖RTTI的功能。
2. 手动实现对应类型的typeinfo符号
GCC对typeinfo符号有固定的名称修饰规则,比如int对应的typeinfo符号实际是_ZTIi(可以用c++filt _ZTIi命令验证,输出就是typeinfo for int)。你可以自己定义一个极简的type_info结构,然后生成对应的符号:
// 极简模拟std::type_info的结构 struct type_info { const char* __name; }; // 定义int对应的typeinfo符号 extern "C" const type_info _ZTIi __attribute__((visibility("default"))) = {"int"};
这样链接器就能找到需要的符号,解决报错问题。
内容的提问来源于stack exchange,提问作者Jade Marker

