什么是C ++"关键功能"如黄金所述?

时间:2017-08-23 22:12:01

标签: c++ gcc ld

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

在gold提供的错误消息中:

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

什么是key function?我在dllimport部分的GCC manual page for Function Attributes下找到了对它的引用。相关文字如下:

  

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

从中我可以看出,在某些条件下,在Symbian OS上使用dllimport属性时,有一些与构造函数或析构函数不同的函数。有意思,但我在Linux上编译Linux,grep -r dllimport没有透露任何内容。所以本段不适用。

(FWIW问题是从未定义的析构函数派生出来的(在本例中),但是文档和链接器的输出都非常痛苦地区分了一个"关键函数"来自析构函数。对于其他类型的缺失符号,链接器会拼写缺失符号的名称。)

那么,什么是key function 真的

2 个答案:

答案 0 :(得分:25)

键函数定义为类中声明的第一个非内联虚函数。 关于它的官方gcc wiki是this

答案 1 :(得分:13)

(从评论中移动/扩展)

正如@navylover所解释的那样,关键功能是在类中定义的第一个非内联虚函数;这很重要,因为它被编译器用作传统标记来决定必须发出什么样的TU(因为它必须只发射一次) - 无论哪个TU包含键函数的定义,相应的对象模块都将包含也是如此。

接下来,如果没有TU定义关键功能(例如因为你忘了定义它),vtable将永远不会被发出,因此错误。

黄金试图暗示你正确的方向:如果缺少vtable,可能是因为关键功能也缺失了(再次,因为你没有定义或忘记链接其模块),尽管它可能没有明确地列为未定义的引用(这可能会使你走上正确的轨道),因为在其余的代码中没有人直接调用它 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

好的,那又怎样?这不像我必须明确定义vtable,所以我不应该在哪里开始寻找修复这种错误。

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