对`vtable的奇怪未定义引用

Xu *_*Hui 12 c++ g++

我困"undefined reference to vtable..."了一整天。

其实我已经看到很多答案 "undefined reference to vtable..."

例如:

未定义对vtable“交易”的引用

未定义对vtable的引用

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

未定义对vtable的引用

有些人的问题是忘记编写虚拟函数,而其他人则忘记了将.cpp文件添加到生成目录。但是我想我已经注意到了。

我要执行以下步骤:

  • 我要编译类A_1A_2转到共享库libAA_2源自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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

A_2.cpp

#include "A_2.h"

void A_2::print()
{
    // empty
}
Run Code Online (Sandbox Code Playgroud)
  • 我要编译类B_1B_2转到共享库libBB_1并且B_2是独立的。

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
Run Code Online (Sandbox Code Playgroud)

B_1.cpp

#include "B_1.h"

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

B_1::~B_1()
{
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)
  • 我想在中使用两个共享库main.cpp。在这里,出了点问题。

main.cpp

#include "B_1.h"
int main()
{
    B_1 b1("name");
}
Run Code Online (Sandbox Code Playgroud)

我正在使用follow命令进行编译:

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
Run Code Online (Sandbox Code Playgroud)

编译器说:

./libB.so: undefined reference to `vtable for A_2'
Run Code Online (Sandbox Code Playgroud)

您会看到许多空函数,因为我忽略了一些无关的代码。但是在这种情况下,它仍然有错误。

有人可以帮我吗?谢谢。

UmN*_*obe 10

编译库B时也要提供共享库A。

g++ B_1.cpp B_2.cpp  -L . -lA  -fPIC -shared -o libB.so
Run Code Online (Sandbox Code Playgroud)

简单地说(我不是该主题的专家),g ++在后台使用的ld链接程序是报告未定义符号的链接程序。编译main时,libB中无法解析的符号无法通过提供libA来解析,因为main 显式使用的所有符号都是使用libB解析的。

默认 :

  • 编译可执行文件时,如果存在未定义的符号,则ld失败
  • 编译库时,如果有未定义的符号,ld不会失败

后者允许您做很多灵活的事情,其中​​包括库之间的循环依赖关系(这里libA也可以依赖libB)。

要在第二步失败,您需要使用来明确告诉链接器失败,如果存在未定义的符号-z defs

g++ B1.cpp B2.cpp -z defs -fPIC -shared -o libB.so
Run Code Online (Sandbox Code Playgroud)

/tmp/cchjkdnAk.o:在函数A_2::A_2()': B2.cpp:(.text._ZN3A_2C2Ev[_ZN3A_2C5Ev]+0x1b): undefined reference to vtable中用于A_2'collect2:错误:ld返回1退出状态

如果main.cpp编写为:

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

libA将被加载来解析main中的符号,而这些符号将被用于libB的丢失符号。

有关更多信息:linux杂志上有一篇不错的文章,它对符号解析进行了更深入的介绍