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

What is a C++ "Key Function" as described by gold?

请不要回答问题"how do I solve this error message?"

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 中找到了对它的引用。相关文字如下:

On the SH Symbian OS target the dllimport attribute also has another affect (sic)—it can cause the vtable and run-time type information for a class to be exported. This happens when the class has a dllimport'ed constructor or a non-inline, non-pure virtual function and, for either of those two conditions, the class also has an inline constructor or destructor and has a key function that is defined in the current translation unit.

从这里我得出结论,在 Symbian OS 上使用 dllimport 属性时,在某些情况下需要一些不同于构造函数或析构函数的函数。有趣,但我在 Linux 上为 Linux 编译,而 grep -r dllimport 没有显示任何内容。所以这段不适用。

(FWIW 问题源自(在这种情况下)未定义的 析构函数 但链接器的文档和输出都竭尽全力区分 "key function" 来自析构函数。对于其他类型的缺失符号,链接器拼写缺失符号的名称。)

那么,什么是key function真的

key 函数被定义为 class 中声明的第一个非内联虚函数。 关于它的官方 gcc wiki 是 here.

(moving/expanding 来自评论)

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

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

gold 正试图向您提示正确的方向:如果 vtable 丢失,可能是因为关键函数也丢失了(同样,因为您没有定义或忘记了 link 它的模块),虽然它可能没有被明确列为未定义的引用(这可能会让你走上正轨)因为在代码的其余部分没有人直接调用它 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. 然而,这样的函数可以通过指向基 class 的指针间接 调用,并且 linker 仍将仅显示对的未定义引用vtable 而不是函数,因为在这种情况下对函数的唯一引用将在 vtable 中,而 vtable 丢失了。