Search code examples
c++g++vtable

Are there flags for g++ that will make these errors easier to read?


I came across these C++ link errors. Maybe not specifically for why these happened, but I'd like know whether there are some g++ flags that may make these error messages more readable, e.g., it doesn't really make sense for these symbols: _ZN9, _ZTI12, +0x10, etc.

g++ -o src/test.o -c -std=c++11 -Iinclude src/test.cpp
g++ -o observer5 src/test.o
src/test.o: In function `CObserver::CObserver()':
test.cpp:(.text._ZN9CObserverC2Ev[_ZN9CObserverC5Ev]+0xf): undefined reference to `vtable for CObserver'
src/test.o:(.rodata._ZTI12CDisplayHeat[_ZTI12CDisplayHeat]+0x10): undefined reference to `typeinfo for CObserver'
src/test.o:(.rodata._ZTI15CDisplayForcast[_ZTI15CDisplayForcast]+0x10): undefined reference to `typeinfo for CObserver'
src/test.o:(.rodata._ZTI13CDisplayStats[_ZTI13CDisplayStats]+0x10): undefined reference to `typeinfo for CObserver'
src/test.o:(.rodata._ZTI15CDisplayCurrent[_ZTI15CDisplayCurrent]+0x10): undefined reference to `typeinfo for CObserver'
collect2: error: ld returned 1 exit status

Solution

  • The term "vtable" is short for "virtual function table." When the compiler generates code for classes that have virtual functions, it assembles a table containing a bunch of pointers to the member functions of each polymorphic class. This table is then used to implement dynamic dispatch extremely efficiently.

    The error you're getting here is a linker error indicating that your code compiled correctly (good!) but that the linker couldn't find the compiled code for the implementation of one or more member functions in a class with a vtable. Since it couldn't find those implementations, it couldn't generate the necessary vtables, so the linker reports that it can't turn the assembly into machine code. The information you're getting about offsets pertains to the generated assembly code, not your source file.

    To fix this error, look over the referenced classes (here, CObserver) and check that, for each member function, you either

    1. defined it somewhere (and correctly compiled the file containing the implementation), or
    2. marked it pure virtual (so there's no missing vtable entry).

    As for how to make these easier to read - I'm not sure. However, I've seen this error enough times that I can immediately tell what the problem is when I see it. I think with practice you'll get into the same boat.