我刚遇到以下错误(并在网上找到了解决方案,但它在Stack Overflow中没有出现):

  

(。gnu.linkonce。[stuff]):undefined   参考[方法] [对象   文件] :( gnu.linkonce [东东])。:   对`的typeinfo的未定义引用   [类名]'

为什么可能会得到其中一个<!>未定义的对typeinfo <!>的引用?链接器错误?

(如果您能解释幕后发生的事情,可以给予奖励。)

有帮助吗?

解决方案

一个可能的原因是因为您在没有定义虚拟函数的情况下声明它。

如果在未在同一编译单元中定义它而声明它,则表明它已在其他位置定义 - 这意味着链接器阶段将尝试在其他编译单元(或库)中找到它。

定义虚拟功能的一个例子是:

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

在这种情况下,您要在声明中附加一个定义,这意味着链接器以后不需要解析它。

该行

virtual void fn();

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

这与代码非常相似:

extern int i;
int *pi = &i;

表示整数i在另一个编译单元中声明,必须在链接时解析(否则pi不能设置为它的地址)。

其他提示

当您混合-fno-rtti-frtti代码时,也会发生这种情况。然后,您需要确保在type_info代码中访问dynamic_cast的任何类都使用<=>编译其密钥方法。当您创建类的对象时,可能会发生此类访问,使用<=>等。

[ source ]

当声明的(非纯)虚函数缺少实体时会发生这种情况。在您的类定义中,类似于:

virtual void foo();

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

virtual void foo() {}

或宣布为纯虚拟:

virtual void foo() = 0;

gcc手册中引用:

  

对于多态类(具有虚函数的类),type_info对象与vtable一起写出[...]对于所有其他类型,我们在使用时写出type_info对象:当应用`typeid'时表达式,抛出对象或引用catch子句或异常规范中的类型。

在同一页面上稍早一点:

  

如果类声明任何非内联非纯虚函数,则第一个被选为<!>#8220; key method <!>#8221;对于类,vtable仅在定义键方法的转换单元中发出。

因此,当<!>“键方法<!>”时会发生此错误。正如其他已经提到的答案一样,它缺少其定义。

如果你将一个.so链接到另一个,那么还有一种可能性是用<!>引用 - -fvisibility = hidden <!>;用gcc或g ++。如果两个.so文件都使用<!>建立; -fvisibility = hidden <!>;并且key方法不是同一个。所以作为虚函数的另一个实现,后者将不会看到前者的vtable或typeinfo。对于链接器,这看起来像一个未实现的虚函数(如paxdiablo和cdleary的答案)。

在这种情况下,您必须使用

对基类的可见性进行例外处理
__attribute__ ((visibility("default")))

在类声明中。例如,

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

另一种解决方案当然是不使用<!>“-fvisibility = hidden。<!>”;这确实使编译器和链接器复杂化,可能会损害代码性能。

以前的答案是正确的,但尝试在具有 no 虚函数的类的对象上使用typeid也会导致此错误。 C ++ RTTI需要一个vtable,因此您希望执行类型识别的类至少需要一个虚函数。

如果您希望类型信息适用于您不想要任何虚函数的类,请将析构函数设为虚拟。

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

a)使用-frtti或-fno-rtti
重新编译所有内容 b)如果a)不可能,请尝试以下方法:

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

定义另一个没有虚拟的类(例如FooAdapter),并将调用转发给您使用的Foo。

在不使用RTTI且仅依赖于libfoo符号的小型静态库中编译FooAdapter。为它提供一个标题,并在您的代码中使用它(使用RTTI)。由于FooAdapter没有虚函数,因此它不具有任何typeinfo,您将能够链接您的二进制文件。如果你使用libfoo中的很多不同的类,这个解决方案可能不方便,但它是一个开始。

我只花了几个小时来解决这个错误,虽然这里的其他答案帮助我理解了发生了什么,但他们没有解决我的特殊问题。

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

重点:将订单MATTERS与<=>相关联。如果列出要以不正确的顺序链接的库,则可能会出现<=>错误。

请参阅这个问题有关将订单与<=> / <=>联系起来的更多细节。

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

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

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

在基类(抽象基类)中,您声明了一个虚拟析构函数,因为您无法将析构函数声明为纯虚函数,您必须在抽象类中定义它,只需虚拟定义,如虚拟~base(){}将执行,或者在任何派生类中执行。

如果你没有这样做,你将以<!>“未定义的符号<!>”结尾;在链接时。 由于VMT具有匹配NULL的所有纯虚函数的条目,因为它根据派生类中的实现更新表。但对于非纯虚函数,它需要在链接时定义,以便它可以更新VMT表。

使用c ++ filt来解码符号。比如$ c ++ filt _ZTIN10storageapi8BaseHostE 将为storageapi :: BaseHost <!>添加类似<!>的类型信息。

我刚才遇到了很多这些错误。发生的事情是我将一个只有头文件的类拆分成头文件和一个cpp文件。但是,我没有更新我的构建系统,因此cpp文件没有被编译。只是对标题中声明但未实现的函数的未定义引用,我得到了很多这些typeinfo错误。

解决方案是重新运行构建系统以编译和链接新的cpp文件。

在我的情况下,我使用了第三方库,包含头文件和文件。我将一个类子类化,并且当我尝试实例化我的子类时发生这样的链接错误。

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

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

还有一件事,如果您选择尝试我的解决方案,请尝试使单独的文件尽可能简单,并且不要使用C ++的一些奇特功能。特别注意提升相关的东西,其中很大一部分取决于rtti。

当我的界面(包含所有纯虚函数)需要一个函数时,我遇到了同样的错误,我忘了<!> quot; null <!> quot;它

我有

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):对ICommProvider的'typeinfo'的未定义引用

进行简单的更改
virtual int vaClose();

virtual int vaClose() = 0;

修复了问题。希望它有所帮助

我遇到一种罕见的情况,但这可能会帮助处于类似情况的其他朋友。我必须使用gcc 4.4.7处理旧系统。我必须使用c ++ 11或更高版本支持编译代码,因此我构建了最新版本的gcc 5.3.0。在构建我的代码并链接到依赖项时,如果使用较旧的编译器构建依赖项,那么即使我使用-L / path / to / lib -llibname明确定义了链接路径,我也得到了'未定义的'错误引用。一些软件包(例如boost和使用cmake构建的项目)通常倾向于使用较旧的编译器,并且它们通常会导致此类问题。你必须走很长的路才能确保他们使用更新的编译器。

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

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

对于某些项目,您必须明确设置它,例如RocksDB:

USE_RTTI=1 make shared_lib -j4
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top