undefined reference to vtable - virtual member, classes generated by gsoap

groovehunter picture groovehunter · Jan 4, 2011 · Viewed 15.9k times · Source

gsoap with its tools wsdl2h and soapcpp2 provided me with a soapStub.h file containing the following:

class SOAP_CMAC ns2__SOAPKunden
{
  public:
    std::string *adresszusatz; 
    // ...
  public:
    virtual int soap_type() const { return 7; }
    // ...
    ns2__SOAPKunden() : adresszusatz(NULL), x(NULL) { }   // left out all member init.
    virtual ~ns2__SOAPKunden() { }
};

I start with a small app using the class to populate objects with data from informix DB.

But to compile successfully i have to leave away all the virtual stuff - i found many postings about this error and use of virtual members in subclasses - otherwise i get

main.o: In function `ns2__SOAPKunden::ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenC1Ev[ns2__SOAPKunden::ns2__SOAPKunden()]+0xf): undefined reference to `vtable for ns2__SOAPKunden'
main.o: In function `ns2__SOAPKunden::~ns2__SOAPKunden()':
main.cpp:(.text._ZN15ns2__SOAPKundenD1Ev[ns2__SOAPKunden::~ns2__SOAPKunden()]+0x13): undefined reference to `vtable for ns2__SOAPKunden'
collect2: ld returned 1 exit status

I admit after years of scripting only it's very hard for me to make sense of C++ code... I want to ask for any advice what to try next. My class is no derived class, is for example what makes me wonder.

Answer

The error means that the virtual table has not been correctly compiled/linked in the final binary (executable or library). There are two common circumstances that lead to this error:

  • you are not linking the object file that includes the virtual table definitions --i.e. you compiled soapStub.cpp into soapStub.o, but did not add that binary to the linker command line.
  • the compiler is not generating the virtual table anywhere, so even if you are including all object files, that does not include the virtual table.

The second case is the hardest to identify for non-experienced developers, and can be caused by a class that is defined in the header and contains virtual functions. If all the virtual functions are defined inlined, the compiler will generate the virtual table in all translation units that include the header, and mark it as a weak symbol so that the linker can discard them, but if you later add a new virtual method and you leave it undefined in the header --or if you remove the definition from one of the virtual functions--, then the compiler will not generate the virtual table in each translation unit, but only in the one that defines those functions.

Things to check:

  • you are linking all object files
  • either all virtual functions are defined inline in the class definition or you have a .cpp that defines the virtual functions and you are linking that in.