“vtable”链接器错误(涉及带有“= default”的虚拟析构函数) - Clang 3.1中的潜在错误?

时间:2012-12-15 10:43:13

标签: c++ gcc llvm clang

我的代码中出现了链接器错误。我已经确定了下面的基本要点。

此代码为链接器提供错误“vtable for Foo”,引自:Foo :: Foo()

class Foo {
public:
  Foo();
  virtual ~Foo() = default;
};
Foo::Foo() { }

但是这段代码没有任何错误:

class Foo {
public:
  Foo();
  virtual ~Foo() { }
};
Foo::Foo() { }

为什么呢?我认为= default基本上与那些空方括号基本相同。

更新:我使用的是“Apple LLVM编译器4.1”,它是Xcode 4.5.2的一部分。它可能是这个编译器中的错误吗?它可能适用于最新的GCC(Apple不再发售)。有关编译器的讨论,请参阅下面的评论。

更新2:如下所述,将行更改为virtual inline ~Foo() = default;可以消除此错误。难道这只是成为一个错误吗?在没有明确写出inline的情况下,看起来编译器无法识别内联函数。

3 个答案:

答案 0 :(得分:3)

It appears to be a bug in clang which has been fixed already.您在很短的时间内问过,因为新版本应该很快就会发布:release candidates are already available。请试一试,您的示例适用于i386-linux二进制版本,并且应该适用于所有这些版本。

答案 1 :(得分:2)

在Itanium ABI中,为包含第一个未在类中内联定义的虚拟方法的定义的转换单元发出v表(和其他RTTI信息),或者如果只有内联定义的虚方法,则为每个包含该课程的翻译单元。然后由链接器合并冗余符号。

有可能通过指定= default,Clang没有意识到您在课程中内联了定义 virtual方法,并且包含您的每个TU file应该定义v-table和RTTI信息,而是等待定义出现在某个地方。

我可以建议将定义在之外吗? => Foo::~Foo() = default;

答案 2 :(得分:1)

它适用于g ++ 4.7.2。但我和clang 3.1有同样的问题。

我有3个文件。

foo.h中:

#ifndef FOO_H
#define FOO_H

class Foo {
public:
  Foo();
  virtual ~Foo() = default;
};

#endif // FOO_H

Foo.cpp中:

#include "Foo.h"

Foo::Foo() { }

main.cpp中:

#include <iostream>
#include "Foo.h"

using namespace std;

int main()
{
    Foo foo;
    return 0;
}

但如果是这样的话,它也适用于clang:

Foo.cpp为空。

的main.cpp

#include <iostream>
#include "Foo.h"

using namespace std;

Foo::Foo() { }

int main()
{
    Foo foo;
    return 0;
}

所以我猜clang在生成目标文件时有错误。