黄金描述的C++ "Key Function"是什么?



请不要回答"如何解决此错误消息?

在 gold 提供的错误消息中:

/usr/bin/ld.gold: the vtable symbol may be undefined
because the class is missing its key function

什么是key function?我在 GCC 手册页面的函数属性第dllimport部分下找到了对它的引用。相关案文如下:

在 SH Symbian OS 目标上,dllimport 属性还有另一个影响(原文如此(——它可能导致导出类的 vtable 和运行时类型信息。当类具有 dllimport 构造函数或非内联、非纯虚函数时,就会发生这种情况,并且对于这两个条件中的任何一个,该类还具有内联构造函数或析构函数,并且具有在当前翻译单元中定义的键函数。

由此我得出,有一些不同于构造函数或析构函数的功能,在某些情况下,在 Symbian OS 上使用dllimport属性时是必需的。 很有趣,但我正在为 Linux 上的 Linux 编译,grep -r dllimport什么也没显示。所以这一段不适用。

(FWIW 问题(在本例中(源自未定义的析构函数,但链接器的文档和输出都竭尽全力将"关键函数"与析构函数区分开来。对于其他类型的缺失符号,链接器会拼写缺失符号的名称。

那么,key function到底是什么?

键函数被定义为类中声明的第一个非内联虚函数。 关于它的官方 gcc 维基在这里。

(从注释移动/扩展(

正如@navylover所解释的,key函数是类中定义的第一个非内联虚函数;这很重要,因为它被编译器用作常规标记来决定必须在哪个TU中发出vtable(因为它必须只发出一次( - 无论哪个TU包含键函数的定义,相应的对象模块也将包含vtable。

因此,如果没有 TU 定义键函数(例如,因为您忘记定义它(,则 vtable 将永远不会发出,因此会出现错误。

Gold在那里试图暗示你正确的方向:如果vtable丢失,可能是因为key函数也丢失了(同样,因为你没有定义或忘记链接它的模块(,尽管它可能没有被明确列为未定义的引用(这可能会让你走上正确的轨道(,因为在其余的代码中没有人直接调用它1,如本例所示:

struct Test {
virtual void foo();
virtual int bar() {
return 0;
}
};
int main() {
Test t;
t.bar();
return 0;
}

 

[matteo@teolapkubuntu /tmp]$ g++ -fuse-ld=gold keyf.cpp 
/tmp/ccduMsT3.o:keyf.cpp:function main: error: undefined reference to 'vtable for Test'
/usr/bin/ld.gold: the vtable symbol may be undefined because the class is missing its key function

将其与常规的GNU ld进行比较,它只是说

[matteo@teolapkubuntu /tmp]$ g++ keyf.cpp 
/tmp/ccUr3Xyi.o: In function `main':
keyf.cpp:(.text+0x1a): undefined reference to `vtable for Test'
collect2: error: ld returned 1 exit status

好吧,那又怎样?这并不是说我必须明确定义 vtables,所以绝对不清楚我应该从哪里开始寻找修复这种错误。


  1. 但是,可以通过指向基类的指针间接调用此类函数,并且链接器仍将仅显示对 vtable 的未定义引用,而不显示对函数的未定义引用,因为在这种情况下,对函数的唯一引用将在缺少的 vtable 中。

最新更新