编译以下代码给出“对`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 中的某种错误?
这似乎是 Bug 28280,由 https://reviews.llvm.org/D45898:
修复如果花括号初始化列表中的初始值设定项是具有重要析构函数的 C++ 类,请将析构函数标记为已引用。这修复了 CodeGenFunction::destroyCXXObject 尝试在堆栈展开路径上发出对析构函数的调用但该类的 CXXRecordDecl 没有析构函数的 CXXDestructorDecl 时发生的崩溃。
此示例确实使用了花括号初始化列表,并在调用
_Unwind_Resume
之前发出析构函数调用。析构函数并不简单。将初始化更改为使用 ()
而不是 {}
会使错误消失,因为它不再使用花括号初始化列表进行初始化。我的评论中的析构函数调用可能会导致析构函数被标记为引用。也许启用优化会产生相同的效果,使其仅出现在非平凡的析构函数中。