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

时间:2018-11-01 15:09:13

标签: c++ visual-c++-2015 visual-c++-2017

我有一个简单的单成员结构,其中删除了副本构造/分配,并且默认移动构造/分配。我试图通过值将这些结构之一传递给函数并返回成员-非常简单。

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之类的东西似乎没有受到影响。结构大小似乎也是一个因素。

1 个答案:

答案 0 :(得分:1)

除了严重的编译器错误外,我看不到其他任何东西。该代码有效。

在两个MSVS版本中已经打破了如此基本的规定,这似乎有些奇怪,但是如果我不得不猜测,那是由于相对较新的C ++ 17复制省略支持。 (当然,在这种情况下,我会稍微宽松地使用“支持”一词。)

(OP的VS错误在线上提出,here