Software: September 2011 Archives

 

September 2, 2011

Note to self, when you see the following error:

Undefined symbols for architecture x86_64:
  "vtable for Foo", referenced from:
      Foo::Foo()   in ccqNJSZ0.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

It means you have declared virtual functions but you haven't defined any of them non-inline. Here's the code that caused this:

class Foo {
    virtual void f();
};

int main(int argc, char **argv)
{
  Foo foo;

  return(0);
}

Now, it's true that you would expect a linkage error here, but not this linkage error. Rather, you'd appear to get a complaint about function f() being missing, which is what happens when you change the class definition a bit to have f() defined but b() undefined.

class Foo {
    virtual void f();
    virtual void b();
};
void Foo::f() {}

This gives the expected error:

Undefined symbols for architecture x86_64:
  "Foo::b()", referenced from:
      vtable for Fooin ccxuo26H.o
ld: symbol(s) not found for architecture x86_64

What's going on here is described in a GCC FAQ entry:

The ISO C++ Standard specifies that all virtual methods of a class that are not pure-virtual must be defined, but does not require any diagnostic for violations of this rule [class.virtual]/8. Based on this assumption, GCC will only emit the implicitly defined constructors, the assignment operator, the destructor and the virtual table of a class in the translation unit that defines its first such non-inline method.

Therefore, if you fail to define this particular method, the linker may complain about the lack of definitions for apparently unrelated symbols. Unfortunately, in order to improve this error message, it might be necessary to change the linker, and this can't always be done.

Pretty sweet, huh?