这个问题在试图throw一个int时有可能出现。在网上搜了很多,类似的问题都是关于自定义类型的,解决办法就是确认所有虚函数都被正确定义。然而对于int,因为是基础类型,所以不存在虚函数,所以网上已有的解决方案均不适用。经过一番研究,本文全网独家发布此问题解决方案!
必须在这里踩一脚StackOverflow,明明一个史无前例的新问题,管理员二话不说就给我关掉了,尽显傲慢,等我解决了问题,因为已经关闭了所以也回答不了,那就别怪爷不伺候你们这群鬼佬了。
注意,此解决方案仅适用于GCC,但对于其它编译器亦可以类似思路尝试解决。
解决方法
实际上,GCC会将所有基础数据类型的typeinfo交给一个叫做__cxxabiv1::__fundamental_type_info的类来处理。链接时找不到基础数据类型的typeinfo,本质上就是因为这个类没定义。一般来说,这个类会定义在<cxxabi.h>中。这是GCC专用的内部头文件,不是C++标准头文件。现在你需要在这个头文件中确认这个类的定义是否存在:
// Type information for int, float etc.
class __fundamental_type_info : public std::type_info
{
public:
explicit
__fundamental_type_info(const char* __n) : std::type_info(__n) { }
virtual
~__fundamental_type_info();
};
如果不存在,你将需要手动添加这个类。不一定非得定义在<cxxabi.h>中,而是可以定义在任何编译单元中,只要确保在链接时能找到它即可。
注意到在上述代码中,此类的构造函数已定义,但析构函数未定义。因此如果这个类存在但仍然报错,你还需要检查这个类是否有函数未定义。同样,你可以在任何编译单元中定义这个类的函数:
#include "tinfo.h"
namespace __cxxabiv1 {
// This has special meaning to the compiler, and will cause it
// to emit the type_info structures for the fundamental types which are
// mandated to exist in the runtime.
__fundamental_type_info::
~__fundamental_type_info ()
{}
}
正常情况下,这个析构函数会定义在fundamental_type_info.cc中。如果没有定义,你可以在你自己的代码中定义。
至此,编译通过,问题解决!
后话
如果你仔细研读<cxxabi.h>,就会发现它还包含了用于处理函数、指针、枚举等更多类型的typeinfo的类型。这些类型中任何一个如果没有完整定义,都会导致对应的typeinfo缺失,进而无法throw。如果你遇到其它类似问题,也可以检查一下这个头文件,或许会得到一些灵感。
这个头文件是GCC专用的,在其它编译器中未必提供。但是,其它编译器处理typeinfo的方法也可能是类似的,它们也可能会提供一些具有其它名称的头文件,定义一些具有其它名称的类型,来实现throw。这可能需要你去浏览你的编译器提供的标准库代码,特别是那些不在C++标准中的编译器特定代码。