Clang中出现析构函数的未定义引用问题

4

编译以下代码会出现 "undefined reference to `A::~A()" 错误:

#include <cstdlib>
#include <memory>

template <typename T>
struct A {
        A() {}
        ~A() {}
};

struct Aggregate {
        using key_vector = A<char>;
        using value_vector = A<int>;

        value_vector vals;
        key_vector keys;
};

int
main()
{
        auto x = malloc(sizeof(Aggregate));
        new (x) Aggregate{};

        return 0;
}

问题出现在clang 7.0和6.0上(可能也存在于一些旧版本中),请参见:https://godbolt.org/z/GNPk3V
在较新的clang版本和gcc上它能够正常工作。
这是预期的吗?还是clang中的某种错误?

4
如果有帮助的话,有两件事都可以解决这个错误:使用一些-O级别进行编译;以及在从“main”返回之前插入((Aggregate*)x)->~Aggregate();。不要问我为什么它们中的任何一个起作用。 - chris
2
或者使用= default来定义析构函数。或者直接删除它,因为它是空的。我不知道为什么会出现这种情况,但在调用析构函数并删除内存的实际代码中不应该发生这种情况。 - DeiDei
1
~A() = 默认值; - jignatius
如果不再发生,那么我会认为这是一个已经修复的错误。 - Max Langhof
1个回答

4

这似乎是Bug 28280,由https://reviews.llvm.org/D45898修复:

如果花括号初始化列表中的初始化器是一个具有非平凡析构函数的C++类,则将析构函数标记为已引用。这将修复CodeGenFunction::destroyCXXObject中的崩溃,当它试图在堆栈展开路径上发出对析构函数的调用时,但该类的CXXRecordDecl没有一个CXXDestructorDecl的析构函数。

此示例确实使用了花括号初始化列表,并在调用_Unwind_Resume之前立即发出了析构函数调用。析构函数是非平凡的。将初始化更改为使用()而不是{}可以消除错误,因为它不再使用花括号初始化列表进行初始化。我的评论中的析构函数调用可能会导致将析构函数标记为已引用。也许启用优化会与使这仅对非平凡析构函数可见的相同因素产生影响。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接