MSVC 将仅移动结构参数解释为指针
MSVC interpreting move-only struct argument as a pointer
我有一个简单的单成员结构,其中包含已删除的副本 construction/assignment 和默认移动 construction/assignment。我试图通过值和 return 成员将这些结构之一传递给函数 - 非常简单。
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*
,随后的成员读取会导致分段错误。
这里有一个godbolt的例子,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
编辑 #2:如果像我一样,您遇到了类似的问题并且无法轻松更新 VS - 似乎手动定义移动 constructor/assignment 运算符 而不是使用 = default
导致 MSVC 在调用站点吐出正确的代码并避免崩溃。 here's a new godbolt
因此,std::unique_ptr 之类的内容似乎没有受到影响。结构大小似乎也是一个因素。
除了严重的编译器错误,我看不出这是什么。代码有效。
在两个 MSVS 版本中已经破坏了如此基础的东西,这似乎确实很奇怪,但如果我不得不猜测这可能是由于相对较新的 C++17 复制省略支持。 (当然,在这种情况下,我使用的术语 "support" 有点松散。)
(网上提出的OP的VS bug here.)
我有一个简单的单成员结构,其中包含已删除的副本 construction/assignment 和默认移动 construction/assignment。我试图通过值和 return 成员将这些结构之一传递给函数 - 非常简单。
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*
,随后的成员读取会导致分段错误。
这里有一个godbolt的例子,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
编辑 #2:如果像我一样,您遇到了类似的问题并且无法轻松更新 VS - 似乎手动定义移动 constructor/assignment 运算符 而不是使用 = default
导致 MSVC 在调用站点吐出正确的代码并避免崩溃。 here's a new godbolt
因此,std::unique_ptr 之类的内容似乎没有受到影响。结构大小似乎也是一个因素。
除了严重的编译器错误,我看不出这是什么。代码有效。
在两个 MSVS 版本中已经破坏了如此基础的东西,这似乎确实很奇怪,但如果我不得不猜测这可能是由于相对较新的 C++17 复制省略支持。 (当然,在这种情况下,我使用的术语 "support" 有点松散。)
(网上提出的OP的VS bug here.)