86 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
Missing Key Function
 | 
						|
====================
 | 
						|
 | 
						|
If your build failed with a linker error something like this::
 | 
						|
 | 
						|
  foo.cc:28: error: undefined reference to 'vtable for C'
 | 
						|
  the vtable symbol may be undefined because the class is missing its key function
 | 
						|
  (see https://lld.llvm.org/missingkeyfunction)
 | 
						|
 | 
						|
it's likely that your class C has a key function (defined by the ABI as the first
 | 
						|
non-pure, non-inline, virtual function), but you haven't actually defined it.
 | 
						|
 | 
						|
When a class has a key function, the compiler emits the vtable (and some other
 | 
						|
things as well) only in the translation unit that defines that key function. Thus,
 | 
						|
if you're missing the key function, you'll also be missing the vtable. If no other
 | 
						|
function calls your missing function, you won't see any undefined reference errors
 | 
						|
for it, but you will see undefined references to the vtable symbol.
 | 
						|
 | 
						|
When a class has no non-pure, non-inline, virtual functions, there is no key
 | 
						|
function, and the compiler is forced to emit the vtable in every translation unit
 | 
						|
that references the class. In this case, it is emitted in a COMDAT section,
 | 
						|
which allows the linker to eliminate all duplicate copies. This is still
 | 
						|
wasteful in terms of object file size and link time, so it's always advisable to
 | 
						|
ensure there is at least one eligible function that can serve as the key function.
 | 
						|
 | 
						|
Here are the most common mistakes that lead to this error:
 | 
						|
 | 
						|
Failing to define a virtual destructor
 | 
						|
--------------------------------------
 | 
						|
 | 
						|
Say you have a base class declared in a header file::
 | 
						|
 | 
						|
  class B {
 | 
						|
  public:
 | 
						|
    B();
 | 
						|
    virtual ~B();
 | 
						|
    ...
 | 
						|
  };
 | 
						|
 | 
						|
Here, ``~B`` is the first non-pure, non-inline, virtual function, so it is the key
 | 
						|
function. If you forget to define ``B::~B`` in your source file, the compiler will
 | 
						|
not emit the vtable for ``B``, and you'll get an undefined reference to "vtable
 | 
						|
for B".
 | 
						|
 | 
						|
This is just an example of the more general mistake of forgetting to define the
 | 
						|
key function, but it's quite common because virtual destructors are likely to be
 | 
						|
the first eligible key function and it's easy to forget to implement them. It's
 | 
						|
also more likely that you won't have any direct references to the destructor, so
 | 
						|
you won't see any undefined reference errors that point directly to the problem.
 | 
						|
 | 
						|
The solution in this case is to implement the missing function.
 | 
						|
 | 
						|
Forgetting to declare a virtual function in an abstract class as pure
 | 
						|
---------------------------------------------------------------------
 | 
						|
 | 
						|
Say you have an abstract base class declared in a header file::
 | 
						|
 | 
						|
  class A {
 | 
						|
  public:
 | 
						|
    A();
 | 
						|
    virtual ~A() {}
 | 
						|
    virtual int foo() = 0;
 | 
						|
    ...
 | 
						|
    virtual int bar();
 | 
						|
    ...
 | 
						|
  };
 | 
						|
 | 
						|
This base class is intended to be abstract, but you forgot to mark one of the
 | 
						|
functions pure. Here, ``A::bar``, being non-pure, is nominated as the key function,
 | 
						|
and as a result, the vtable for ``A`` is not emitted, because the compiler is
 | 
						|
waiting for a translation unit that defines ``A::bar``.
 | 
						|
 | 
						|
The solution in this case is to add the missing ``= 0`` to the declaration of
 | 
						|
``A::bar``.
 | 
						|
 | 
						|
Key function is defined, but the linker doesn't see it
 | 
						|
------------------------------------------------------
 | 
						|
 | 
						|
It's also possible that you have defined the key function somewhere, but the
 | 
						|
object file containing the definition of that function isn't being linked into
 | 
						|
your application.
 | 
						|
 | 
						|
The solution in this case is to check your dependencies to make sure that
 | 
						|
the object file or the library file containing the key function is given to
 | 
						|
the linker.
 |