首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对“`vtable”的奇怪的未定义引用

对“`vtable”的奇怪的未定义引用
EN

Stack Overflow用户
提问于 2019-05-15 11:52:20
回答 1查看 1.3K关注 0票数 12

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

事实上,我见过很多关于"undefined reference to vtable..."的回答

例如:

未定义的对vtable“事务”的引用

未定义的对vtable的引用

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

未定义的对vtable的引用

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

我想做以下步骤:

  • 我希望将类A_1A_2编译到共享库libA中。A_2是从A_1派生出来的。

A_1.h

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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

代码语言:javascript
复制
#include "A_2.h"

void A_2::print()
{
    // empty
}
  • 我希望将类B_1B_2编译到共享库libB中。B_1B_2是独立的。

B_1.h

代码语言:javascript
复制
#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

代码语言:javascript
复制
#include "B_1.h"

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

B_1::~B_1()
{
}

B_2.h

代码语言:javascript
复制
#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

代码语言:javascript
复制
#include "B_2.h"
#include "A_1.h"
#include "A_2.h"

void B_2::fun()
{
    A_1 *ptr = new A_2;
}
  • 我想在main.cpp中使用两个共享库。在这里,有些事情出了问题。

main.cpp

代码语言:javascript
复制
#include "B_1.h"
int main()
{
    B_1 b1("name");
}

我使用以下命令编译:

代码语言:javascript
复制
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

编译器说:

代码语言:javascript
复制
./libB.so: undefined reference to `vtable for A_2'

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

有人能帮我吗?谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-15 12:07:51

在编译库B时还提供共享库A。

代码语言:javascript
复制
g++ B_1.cpp B_2.cpp  -L . -lA  -fPIC -shared -o libB.so

简单地说(我不是这方面的专家),g++在引擎盖下使用的ld链接器是报告未定义符号的链接器。在编译main时,libB中未解析的符号不能通过提供libA来解析,因为所有显式使用的符号( by main )都使用libB解析。

默认情况下:

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

后者允许您执行许多灵活的操作,其中包括库之间的循环依赖关系(这里,libA也可以依赖于libB)。

要在第二步失败,需要使用-z defs显式地告诉链接器如果有未定义的符号就失败。

代码语言:javascript
复制
g++ B1.cpp B2.cpp -z defs -fPIC -shared -o libB.so

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

如果将main.cpp编写为:

代码语言:javascript
复制
#include "A_2.h"
#include "B_1.h"
int main()
{
    A_1 *ptr = new A_2;
    B_1 b1("name");
}

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

有关更多信息: linux期刊上有一篇很好的文章,它更深入地讨论符号解析。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56148734

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档