我有一个简单的单成员结构,其中删除了复制构造/分配和默认移动构造/分配。我试图通过值将这些结构之一传递给函数并返回成员 - 非常简单。
struct NoCopy {
explicit NoCopy(int x) : x{x} {}
NoCopy(const NoCopy&) = delete;
NoCopy& operator=(const NoCopy&) = delete;
NoCopy(NoCopy&&) = default;
NoCopy& operator=(NoCopy&&) = default;
int x;
};
// noinline to ensure the crash is reproducible in release
// not required to reproduce the problem code
__declspec(noinline) int problem_function(NoCopy x) {
return x.x;
}
int main() {
return problem_function(NoCopy{ 1 });
}
问题是当用 MSVC 编译时,这个函数会崩溃。
查看反汇编,似乎当复制构造函数被删除时,MSVC 尝试解释x
为好像它是 aNoCopy*
并且随后的成员读取导致分段错误。
这是一个godbolt示例,gcc和clang供参考:https ://godbolt.org/z/jG7kIw
请注意,gcc 和 clang 的行为都符合预期。另请注意,这在优化和未优化的版本中都会发生,并且似乎会影响 MSVC 2015 和 2017。
作为参考,我正在使用 Visual Studio Professional 2015(14.0.25431.01 更新 3)在我的机器上编译 - 我主要测试 x64 版本。我的崩溃重现平台工具集设置为 v140。
所以我的问题是:对此是否有任何合理的解释,或者我是否正在查看编译器错误。
编辑:我在这里提交了一个错误报告
编辑#2:如果像我一样,您遇到了类似的问题并且无法轻松更新 VS -手动定义移动构造函数/赋值运算符而不是使用似乎= default
会导致 MSVC 在调用站点吐出正确的代码并避免迷恋;撞车;崩溃。这是一个新的神螺栓
出于这个原因,像 std::unique_ptr 这样的东西似乎没有受到影响。结构大小似乎也是一个因素。