g ++对typeinfo的未定义引用

我只是遇到以下错误(并find解决scheme在线,但它不存在堆栈溢出):

(.gnu.linkonce。[stuff]):未定义的引用[方法] [目标文件] 🙁 .gnu.linkonce。[stuff]):未定义的引用`typeinfo for [classname]'

为什么会得到这些“未定义的引用typeinfo”链接器错误之一?

(如果你可以解释幕后发生了什么,奖金分数。)

一个可能的原因是因为你正在声明一个虚函数而没有定义它。

当你在同一个编译单元中没有定义它的时候声明它,你就表明它是在其他地方定义的 – 这意味着链接器阶段将尝试在其他编译单元(或库)中find它。

定义虚函数的一个例子是:

 virtual void fn() { /* insert code here */ } 

在这种情况下,您要为声明附加一个定义,这意味着链接器不需要稍后parsing。

该线

 virtual void fn(); 

声明fn()而不定义它,并会导致你询问的错误信息。

这与代码非常相似:

 extern int i; int *pi = &i; 

其中规定整数i是在另一个编译单元中声明的,必须在链接时parsing(否则pi不能设置为它的地址)。

在混合-fno-rtti-frtti代码时也会发生这种情况。 然后,您需要确保在-frtti代码中访问的type_info类的任何类都使用-frtti编译了其关键方法。 这样的访问可以在创build类的对象时使用,使用dynamic_cast等。

[ 来源 ]

当声明的(非纯的)虚拟函数是缺less的主体时,会发生这种情况。 在你的类定义中,像这样:

 virtual void foo(); 

应该定义(内联或链接的源文件):

 virtual void foo() {} 

或者宣布纯粹的虚拟:

 virtual void foo() = 0; 

从gcc手册引用:

对于多态类(具有虚函数的类),type_info对象与vtable一起被写出[…]对于所有其他types,我们在使用type_info对象时写出它:当将`typeid'应用于expression式时,抛出一个对象,或者在catch子句或exception规范中引用一个types。

并在同一页上稍早:

如果类声明了任何非内联非纯虚函数,则第一个类被选为该类的“关键方法”,而vtable只在定义了密钥方法的翻译单元中发出。

所以,这个错误发生在“键方法”缺less其定义的时候,因为已经提到了其他的答案。

如果将一个.so链接到另一个,还有一种可能性是在gcc或g ++中使用“-fvisibility = hidden”进行编译。 如果两个.so文件都是用“-fvisibility = hidden”构build的,而key方法与另一个虚拟函数的实现不是一回事,那么后者将不会看到前者的vtable或typeinfo。 对于链接器来说,这看起来像一个未实现的虚函数(就像在paxdiablo和cdleary的答案中一样)。

在这种情况下,您必须为基类的可见性制定一个例外

 __attribute__ ((visibility("default"))) 

在类声明中。 例如,

 class __attribute__ ((visibility("default"))) boom{ virtual void stick(); } 

另一个解决scheme当然是不使用“-fvisibility = hidden”。 这确实使编译器和链接器变得复杂,可能会损害代码的性能。

以前的答案是正确的,但是这个错误也可能是由于尝试在没有虚函数的类的对象上使用typeid引起的。 C ++ RTTI需要一个vtable,所以你希望执行types识别的类至less需要一个虚函数。

如果你想让types信息在你不需要任何虚函数的类上工作,那么使析构函数变成虚拟的。

处理RTTI和非RTTI库的代码的可能解决scheme:

a)用-frtti或-fno-rtti重新编译所有内容
b)如果a)不适合您,请尝试以下操作:

假设libfoo是在没有RTTI的情况下构build的。 你的代码使用libfoo并与RTTI编译。 如果在libfoo中使用具有虚拟的类(Foo),则可能会遇到以下链接时错误:缺less类Foo的typeinfo。

定义另一个没有虚拟的类(例如FooAdapter),并将呼叫转移到您使用的Foo。

在不使用RTTI的小型静态库中编译FooAdapter,只依赖于libfoo符号。 为它提供一个头文件,并在代码中使用它(使用RTTI)。 由于FooAdapter没有虚函数,它不会有任何types信息,你可以链接你的二进制文件。 如果你使用libfoo中的很多不同的类,这个解决scheme可能不方便,但这是一个开始。

我只是花了几个小时在这个错误,而这里的其他答案帮助我了解发生了什么事情,他们没有解决我的特定问题。

我正在编写一个使用clang++g++编译的项目。 我没有使用clang++链接问题,但得到了undefined reference to 'typeinfo for错误与g++

重要的一点是:链接顺序与g++ 。 如果列出要链接的库的顺序不正确,则可能会出现typeinfo错误。

看到这个问题的更多细节链接顺序与gcc / g++

与上面的RTTI,NO-RTTI讨论类似,如果使用dynamic_cast并且未能包含包含类实现的对象代码,也会出现此问题。

我遇到了在Cygwin上构build的这个问题,然后将代码移植到了Linux上。 make文件,目录结构甚至是gcc版本(4.8.2)在两种情况下都是相同的,但是代码在Cygwin上正确链接和运行,但是在Linux上无法链接。 红帽Cygwin显然做了编译器/链接器修改,避免了目标代码链接的要求。

Linux链接器错误消息正确地指引我dynamic_cast行,但在这个论坛的早期消息让我寻找缺less的function实现,而不是实际的问题:缺less对象代码。 我的解决方法是replace基类和派生类中的虚拟types函数,例如virtual int isSpecialType(),而不是使用dynamic_cast。 这种技术避免了链接对象实现代码的要求,以使dynamic_cast正常工作。

在基类(一个抽象的基类)中,你声明了一个虚析构函数,因为你不能把析构函数声明为纯虚函数,要么你必须在抽象类中定义它,而只需要像virtual〜base ){}会做,或者在任何派生类中。

如果你没有做到这一点,你会在链接的时候以“未定义的符号”结束。 由于VMT有一个条目,所有纯虚拟函数都有一个匹配的NULL,因为它根据派生类中的实现来更新表。 但对于非纯粹但虚拟的function来说,需要在链接时进行定义,才能更新VMT表。

用c ++ filt去掉符号。 就像$ c ++ filt _ZTIN10storageapi8BaseHostE会输出类似于“typeinfo for storageapi :: BaseHost”。

我刚刚得到了很多这些错误。 发生了什么事情是我将一个头文件类拆分成一个头文件和一个cpp文件。 但是,我没有更新我的编译系统,所以cpp文件没有被编译。 其中简单地有未定义的引用在头中声明的function,但没有实现,我得到了很多这些typeinfo错误。

解决方法是重新运行构build系统来编译和链接新的cpp文件。

在我的情况下,我用头文件等文件的第三方库。 我subclassed一个类,并链接错误发生,当我尝试实例化我的子类。

正如@sergiy所提到的,我们知道它可能是'rtti'的问题,我设法通过将构造函数实现放入单独的.cpp文件中,并将'-fno-rtti'编译标志应用于文件来解决这个问题 。 它运作良好。

因为我对这个链接错误的内部还不太清楚,所以我不确定我的解决scheme是否一般。 不过,我认为在尝试使用@francois提到的适配器方法之前,这是值得的。 当然,如果所有的源代码都可用(不是我的情况),如果可能的话,最好用“-frtti”重新编译。

还有一件事,如果您select尝试我的解决scheme,请尽可能简单地制作单独的文件,而不要使用C ++的一些奇特function。 要特别注意提升相关的东西,其中大部分取决于rtti。

我遇到一种罕见的情况,但这可能会帮助其他类似情况的朋友。 我必须使用gcc 4.4.7工作在一个较旧的系统上。 我必须用c ++ 11或以上的支持编译代码,所以我构build了最新版本的gcc 5.3.0。 当构build我的代码并链接到依赖关系时,如果依赖关系是使用较旧的编译器构build的,那么即使我使用-L / path / to / lib -llibname清楚地定义了链接path,我也得到了'undefined reference to'错误。 一些软件包如boost和使用cmake构build的项目通常倾向于使用较旧的编译器,并且通常会导致这样的问题。 你必须走很长的路,以确保他们使用较新的编译器。

当我的界面(所有纯虚函数)需要一个更多的function,我忘记“空”它,我有同样的错误。

我有

class ICommProvider { public: /** * @brief If connection is established, it sends the message into the server. * @param[in] msg - message to be send * @return 0 if success, error otherwise */ virtual int vaSend(const std::string &msg) = 0; /** * @brief If connection is established, it is waiting will server response back. * @param[out] msg is the message received from server * @return 0 if success, error otherwise */ virtual int vaReceive(std::string &msg) = 0; virtual int vaSendRaw(const char *buff, int bufflen) = 0; virtual int vaReceiveRaw(char *buff, int bufflen) = 0; /** * @bief Closes current connection (if needed) after serving * @return 0 if success, error otherwise */ virtual int vaClose(); };

最后vaClose不是虚拟的,所以编译不知道从哪里得到实现,从而弄糊涂了。 我的消息是:

… TCPClient.o :(。rodata + 0x38):对'typeinfo for ICommProvider'的未定义引用

从简单的变化

 virtual int vaClose(); 

 virtual int vaClose() = 0; 

解决了这个问题。 希望能帮助到你