Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

gcc

ld

Please do not answer the question "how do I solve this error message?"

In the error message provided by gold:

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

What is a key function? I find reference to it in the GCC manual page for Function Attributes under the section dllimport. The relevant text reads:

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.

From this I take away that there is some function distinct from constructors or destructors, required under some conditions, when using the dllimport attribute, on Symbian OS. Interesting, but I'm compiling for Linux on Linux, and grep -r dllimport reveals nothing. So this paragraph does not apply.

(FWIW the problem derives (in this instance) from an undefined destructor but both the documentation and the output of the linker go to great pains to distinguish a "key function" from a destructor. For other kinds of missing symbols, the linker spells the name of the missing symbol.)

So, what is a key function really?

like image 248
Cuadue Avatar asked Aug 23 '17 22:08

Cuadue


2 Answers

key function is defined as the first non-inline, virtual function declared in the class. The official gcc wiki about it is here.

like image 106
navylover Avatar answered Nov 12 '22 02:11

navylover


(moving/expanding from the comment)

As @navylover explained, the key function is the first non-inline, virtual function defined in the class; it's important because it is used by the compiler as a conventional marker to decide in what TU the vtable must be emitted (as it must be emitted just once) - whichever TU contains the definition of the key function, the corresponding object module will contain the vtable as well.

It follows that, if no TU defines the key function (e.g. because you forgot to define it), the vtable will never get emitted, hence the error.

gold there is trying to hint you in the right direction: if the vtable is missing, probably is because the key function is missing as well (again, either because you didn't define or forgot to link its module), although it may not be listed explicitly as an undefined reference (which could put you on the right track) because in the rest of the code nobody invokes it directly1, as in this example:

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

Compare this with regular GNU ld, which just says

[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

Ok, so what? It's not like I have to explicitly define vtables, so it's definitely not obvious where should I start to look to go fixing this kind of error.


  1. Such a function may however be invoked indirectly through a pointer to base class, and the linker would still show only the undefined reference to the vtable and not to the function, as the only reference to the function in this case would be in the vtable, which is missing.
like image 43
Matteo Italia Avatar answered Nov 12 '22 02:11

Matteo Italia