简体   繁体   English

MSVC将仅移动结构参数解释为指针

[英]MSVC interpreting move-only struct argument as a pointer

I have a simple one-member struct with deleted copy construction/assignment, and default move construction/assignment. 我有一个简单的单成员结构,删除了复制结构/赋值,以及默认的移动构造/赋值。 I'm trying to pass one of these structs to a function by value and return the member - pretty straightforward. 我试图通过值将这些结构中的一个传递给函数并返回该成员 - 非常简单。

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 });
}

The problem is that when compiled with MSVC, this function crashes. 问题是当使用MSVC编译时,此函数崩溃。

Looking at the disassembly, it appears that when the copy constructor is deleted, MSVC attempts to interpret x as if it were a NoCopy* and the subsequent member read causes a segmentation fault. 查看反汇编,似乎在删除复制构造函数时,MSVC会尝试将x解释为NoCopy* ,并且后续成员读取会导致分段错误。

Here's a godbolt example, with gcc and clang for reference: https://godbolt.org/z/jG7kIw 这是一个godbolt的例子,用gcc和clang作为参考: https ://godbolt.org/z/jG7kIw

Note that both gcc and clang behave as expected. 请注意,gcc和clang都按预期运行。 Also note that this happens in both optimised and unoptimised builds, and appears to affect both MSVC 2015 and 2017. 另请注意,这在优化和未优化的构建中都会发生,并且似乎会影响MSVC 2015和2017。

For reference, I'm compiling on my machine with Visual Studio Professional 2015 (14.0.25431.01 Update 3) - and I'm predominantly testing x64 builds. 作为参考,我正在使用Visual Studio Professional 2015(14.0.25431.01 Update 3)在我的机器上进行编译 - 我主要测试x64版本。 My platform toolset for the crash repro is set to v140. 我的崩溃复制平台工具集设置为v140。

So my question is: are there any reasonable explanations for this, or am I looking at a compiler bug. 所以我的问题是:对此有任何合理的解释,或者我正在查看编译器错误。

edit: I've submitted a bug report over here 编辑:我在这里提交了一份错误报告

edit #2: If like me, you're stuck with a similar problem and are unable to update VS easily - it appears that defining move constructor/assignment operator manually instead of using = default causes MSVC to spit out correct code at the call site and avoids the crash. 编辑#2:如果像我一样,你遇到了类似的问题并且无法轻易更新VS - 似乎手动定义移动构造函数/赋值操作符而不是使用= default会导致MSVC在调用站点吐出正确的代码并避免崩溃。 here's a new godbolt 这是一个新的魔咒

for this reason, things like std::unique_ptr don't seem to be affected. 因此,像std :: unique_ptr这样的东西似乎没有受到影响。 struct size also seems to be a factor. 结构大小似乎也是一个因素。

I can't see how this is anything other than an egregious compiler bug. 除了一个令人震惊的编译器bug之外,我看不出这是怎么回事。 The code is valid. 代码有效。

It does perhaps seem strange that something so fundamental was broken in two MSVS versions already, but if I had to guess it'd be due to relatively new C++17 copy elision support. 在两个MSVS版本中已经破坏了如此基本的东西似乎很奇怪,但如果我不得不猜测它是由于相对较新的C ++ 17拷贝省略支持。 (Of course I am using the term "support" somewhat loosely in this instance.) (当然,在这种情况下,我在某种程度上使用了“支持”一词。)

(OP's VS bug raised online here . ) (OP的错误VS在线筹集这里 。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM