Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 978
groovehunter Avatar asked Jan 04 '11 11:01

groovehunter


People also ask

What does undefined reference to vtable mean?

In summary, there are three key causes of the "undefined reference to vtable" error: A member function is missing its definition. An object file is not being linked. All virtual functions have inline definitions.17-Jun-2010.

How do you fix a undefined reference in C++?

When we compile these files separately, the first file gives “undefined reference” for the print function, while the second file gives “undefined reference” for the main function. The way to resolve this error is to compile both the files simultaneously (For example, by using g++).

What is undefined reference?

The Undefined reference is one of those exceptions that occurred mostly in the C language, as the name suggests that it would occur when some function definition is missing from the script.


2 Answers

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.
like image 193
David Rodríguez - dribeas Avatar answered Oct 13 '22 13:10

David Rodríguez - dribeas


This is what David Rodriguez said, just stated simpler I guess...

I had this situation in my interface class:

class IBase
{
    public:
    virtual void begin(unsigned long);
    virtual void end();
    virtual int available(void) = 0;
    virtual int peek(void) = 0;
    virtual int read(void) = 0;
    virtual void flush(void) = 0;
}

and changed it to this:

class IBase
{
    public:
    virtual void begin(unsigned long) = 0;
    virtual void end() = 0;
    virtual int available(void) = 0;
    virtual int peek(void) = 0;
    virtual int read(void) = 0;
    virtual void flush(void) = 0;
}

which did the trick.

begin() and end() were defined in derived class in a different file, IBase class (interface) was only declared in header and included in few places.

Error from OP only appeared when I set optimizations to none (-O0), any other setting resulted in no error (gcc 4.8).

like image 23
nidalpres Avatar answered Oct 13 '22 13:10

nidalpres