我有一个简单的单成员结构,其中删除了副本构造/分配,并且默认移动构造/分配。我试图通过值将这些结构之一传递给函数并返回成员-非常简单。
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
解释为好像是NoCopy*
,随后读取的成员会导致分段错误。
下面是一个例子,其中包含gcc和clang供参考:https://godbolt.org/z/jG7kIw
请注意,gcc和clang的行为均符合预期。 另请注意,这种情况在优化和未优化的版本中都会发生,并且似乎会影响MSVC 2015和2017。
作为参考,我正在使用Visual Studio Professional 2015(14.0.25431.01更新3)在计算机上进行编译-并且我主要在测试x64构建。我用于崩溃修复的平台工具集设置为v140。
所以我的问题是:是否对此有任何合理的解释,或者我正在查看编译器错误。
编辑:我已经提交了一个错误报告over here
edit#2:如果像我一样,您也会遇到类似的问题,并且无法轻松更新VS-似乎是手动定义了移动构造函数/赋值运算符 而不是使用{{1 }}使MSVC在调用站点吐出正确的代码,并避免崩溃。 here's a new godbolt
因此,好像std :: unique_ptr之类的东西似乎没有受到影响。结构大小似乎也是一个因素。
答案 0 :(得分:1)
除了严重的编译器错误外,我看不到其他任何东西。该代码有效。
在两个MSVS版本中已经打破了如此基本的规定,这似乎有些奇怪,但是如果我不得不猜测,那是由于相对较新的C ++ 17复制省略支持。 (当然,在这种情况下,我会稍微宽松地使用“支持”一词。)
(OP的VS错误在线上提出,here。)