Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

strange undefined reference to `vtable

Tags:

c++

g++

I have trapped in "undefined reference to vtable..." for a whole day.

Actually, I have seen many answer deal with "undefined reference to vtable..."

For example:

undefined reference to vtable "Transaction"

Undefined reference to vtable

https://gcc.gnu.org/faq.html#vtables

Undefined reference to vtable

Some people's problem is forget to write virtual function, others are forget to add the .cpp file into build directory. But I think I have notice that.

I want to do the follow step:

  • I want compile class A_1 and A_2 to a shared library libA. A_2 is derived from A_1.

A_1.h

#ifndef include_A_1_h
#define include_A_1_h
class A_1
{
public:
    A_1() {}
    virtual ~A_1() {} // not pure-virtual function has defined
    virtual void print() = 0;

private:
};
#endif

A_2.h

#ifndef include_A_2_h
#define include_A_2_h
#include "A_1.h"

class A_2 : public A_1
{
public:
    A_2() {}
    ~A_2() {}
    virtual void print();

private:
};
#endif

A_2.cpp

#include "A_2.h"

void A_2::print()
{
    // empty
}
  • I want compile class B_1 and B_2 to a shared library libB. B_1 and B_2 is independent.

B_1.h

#ifndef include_B_1_h
#define include_B_1_h

#include <iostream>
#include <string.h>

class B_1
{
public:
    B_1(const std::string &path);
    ~B_1();

private:
};
#endif

B_1.cpp

#include "B_1.h"

B_1::B_1(const std::string &path)
{
}

B_1::~B_1()
{
}

B_2.h

#ifndef include_B_2_h
#define include_B_2_h

class B_2
{
public:
    B_2() {}
    ~B_2() {}
    void fun();

    private:
    };

#endif

B_2.cpp

#include "B_2.h"
#include "A_1.h"
#include "A_2.h"

void B_2::fun()
{
    A_1 *ptr = new A_2;
}
  • I want to using two shared library in main.cpp. At here, some thing goes wrong.

main.cpp

#include "B_1.h"
int main()
{
    B_1 b1("name");
}

I am using the follow command to compile:

g++ A_2.cpp -fPIC -shared -o libA.so
g++ B_1.cpp B_2.cpp -fPIC -shared -o libB.so
g++ main.cpp -L . -lA -lB

The compiler said that:

./libB.so: undefined reference to `vtable for A_2'

You can see many empty functions, because I ignore some irrelevant code. But in this case, It still have the error.

Could any one help me? Thanks.

like image 436
Xu Hui Avatar asked May 15 '19 11:05

Xu Hui


1 Answers

Provide as well the shared library A when compiling the library B.

g++ B_1.cpp B_2.cpp  -L . -lA  -fPIC -shared -o libB.so

To put it simply (I'm no expert in the subject), the ld linker used by g++ under the hood is the one reporting the undefined symbols. When compiling main, unresolved symbols in libB are not resolved by providing libA because all symbols used explicitly by main are resolved using libB.

By default :

  • when compiling an executable, ld fails if there are undefined symbols
  • when compiling a library, ld doesnt fail if there are undefined symbols

The later allow you to do a lot of flexible stuff, among which is circular dependencies between libraries (here libA could also depend on libB).

To fail at the second step, you need to explicitly tell the linker to fail if there undefined symbols, using -z defs.

g++ B1.cpp B2.cpp -z defs -fPIC -shared -o libB.so

/tmp/cchjkdnAk.o: In function A_2::A_2()': B2.cpp:(.text._ZN3A_2C2Ev[_ZN3A_2C5Ev]+0x1b): undefined reference to vtable for A_2' collect2: error: ld returned 1 exit status

Your compilation directive would have worked if main.cpp was written as :

#include "A_2.h"
#include "B_1.h"
int main()
{
    A_1 *ptr = new A_2;
    B_1 b1("name");
}

libA would have been loaded to resolve symbols in main, and those symbols would have been used for the missing symbols of libB.

for more information : there is a nice article on the linux journal which goes deeper on the symbol resolution

like image 160
UmNyobe Avatar answered Nov 15 '22 20:11

UmNyobe