我只是遇到了以下错误:

(.gnu.linkonce。[内容]):定义 引用[方法][对象] 文件:(.gnu.linkonce。[内容]): 对' typeinfo for '的未定义引用 (名称)的

为什么可能会得到这些“未定义的引用typeinfo”链接错误之一? 有人能解释一下幕后发生了什么吗?


当前回答

在我的情况下,这纯粹是一个库依赖问题,即使我有dynamic_cast调用。在makefile中添加了足够的依赖后,这个问题就消失了。

其他回答

有了这个错误消息,g++的链接器是在告诉你,当需要时,它无法为给定的类组装完整的静态typeinfo描述符。正如许多人已经指出的那样,这很可能是由于缺少虚函数的定义。

但不好的是,错误消息的顺序可能与直觉相反,“对typeinfo的未定义引用”出现在对缺失的虚拟定义的未定义引用之前。这里有一个例子,我刚刚经历过:

/usr/bin/ld: module.o:(.data.rel.ro+0x10): undefined reference to `typeinfo for type_xxx'
/usr/bin/ld: module.o:(.data.rel.ro+0x28): undefined reference to `typeinfo for type_xxx'
/usr/bin/ld: module.o:(.data.rel.ro+0x40): undefined reference to `typeinfo for type_xxx'
/usr/bin/ld: module.o:(.data.rel.ro+0x150): undefined reference to `type_xxx::has_property(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'

因此,type_xxx::has_property(const std::string&)的缺失定义仅作为第四个错误报告。因此,有时跳过那些不理解的错误消息,首先处理那些容易理解的错误消息是有好处的。因为在这种情况下,添加缺失的定义也会修复未定义typeinfo引用的问题。

在我的情况下,这纯粹是一个库依赖问题,即使我有dynamic_cast调用。在makefile中添加了足够的依赖后,这个问题就消失了。

在基类(抽象基类)中声明虚析构函数,因为不能将析构函数声明为纯虚函数,所以要么必须在抽象类中定义它,就像virtual ~base(){}这样的虚拟定义,要么在任何派生类中定义。

如果你没有做到这一点,你将在链接时以一个“未定义的符号”结束。 因为VMT在根据派生类中的实现更新表时,为所有纯虚函数提供了一个带有匹配NULL的条目。但对于非纯虚函数,则需要在链接时定义,以便更新VMT表。

使用c++filt来要求符号。比如$c++filt _ZTIN10storageapi8BaseHostE 将输出类似"typeinfo for storageapi::BaseHost"的内容。

I encounter an situation that is rare, but this may help other friends in similar situation. I have to work on an older system with gcc 4.4.7. I have to compile code with c++11 or above support, so I build the latest version of gcc 5.3.0. When building my code and linking to the dependencies if the dependency is build with older compiler, then I got 'undefined reference to' error even though I clearly defined the linking path with -L/path/to/lib -llibname. Some packages such as boost and projects build with cmake usually has a tendency to use the older compiler, and they usually cause such problems. You have to go a long way to make sure they use the newer compiler.

检查你的依赖是在没有-f-nortti的情况下编译的。

对于某些项目,你必须显式地设置它,比如在RocksDB中:

USE_RTTI=1 make shared_lib -j4