【问题标题】:Undefined symbol to destructor only on MacOS [duplicate]仅在 MacOS 上用于析构函数的未定义符号 [重复]
【发布时间】:2020-06-15 22:25:32
【问题描述】:

在我正在开发的库中,我在头文件中有类似这个模板类的东西:

template <int something>
class Base {
public:
    virtual ~Base();  // Implemented in c++ file
}

class Derived : public Base<100> {
public:
    ~Derived() override = default();
}

析构函数是这样实现的:

template <int something>
Base<something>::~Base() {
    destroyBase();
}

此代码编译为静态库。

然后,我在示例中有此代码:

{
   Derived x;
   x.doSomething();
} // X gets destroyed

我编译可执行文件并链接静态库。这在 Ubuntu 上运行良好,但是当我在 mac 上尝试时,链接失败了

Undefined symbols for architecture x86_64:

  "Base<100>::~Base()", referenced from:

      _main in my_sample.cpp.o

在这两种情况下,我都使用 clang 并使用完全相同的 cmake 设置进行编译。定义了 cpp 文件中定义的所有其他符号。这是唯一未定义的符号。发生了什么?

【问题讨论】:

标签: c++ linker linker-errors static-linking


【解决方案1】:

正如 Sebastian Hoffmann 所说,模板必须在头文件中实现,而不是在 cpp 文件中实现,否则将不可见。这就是我得到未定义符号的原因。

当我在头文件中实现所有内容时,mac 上的构建现在可以工作了。 尽管如此,这并不能解释为什么这只发生在 Mac 上但在 ubuntu 上完美运行。另外,为什么只有析构函数?我在 cpp 文件中实现了 Base 的其他成员函数,它们链接得很好!

更新:我认为只有析构函数无法链接的原因是它是客户端应用程序直接引用的唯一一个。构造函数仅通过派生类构造函数被引用,其他成员函数和 operator= 等东西从未真正被调用过。从 c++ 的角度来看,链接器错误是有道理的,但 Mac 和 ubuntu 之间的区别令人费解。

注意:我正在使用 travis ci 进行构建,这实际上是我在 https://github.com/RotartsiORG/StoneMason 的个人爱好项目(不是很好)

【讨论】:

  • 那么这不是一个真正的答案。您为什么不编辑问题以指定您在不同平台上使用的确切构建命令?
  • 可能会提出一个有趣且具有教育意义的问题,说明为什么这适用于其他平台,因此请务必更新问题。
  • 不要谈论操作系统,而是专注于编译器。这是clanggcc 的问题吗?
  • @tadman 我正在使用 travis ci 构建并同时使用 clang(cmake 也两次检测到 clang++)
  • 编译器版本相同?相同的标志?如果是这样,应该没有区别。
猜你喜欢
  • 2017-12-23
  • 1970-01-01
  • 2022-01-14
  • 2021-08-08
  • 2014-06-23
  • 2020-07-07
  • 2017-05-28
  • 2011-09-30
  • 2012-10-07
相关资源
最近更新 更多