4

我有一个在从 VS2013 过渡到 VS2015 期间出现的小问题示例。在 VS2015 中进一步提到的代码示例会导致浮点无效操作。

在此处输入图像描述

int main()
{
    unsigned int enableBits = _EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID;

    _clearfp();
    _controlfp_s(0, ~enableBits, enableBits);

    int count = 100;
    float array[100];

    for (int i = 0; i < count; ++i)
    {
        array[i] = (float)pow((float)(count - 1 - i) / count, 4); //this causes exception in VS2015
    }

    return 0;
}

这仅在发布模式下发生,因此可能是由不同的优化引起的。这段代码有问题还是 VS 2015 中的错误?

在整个代码库中很难找到这样的问题,所以我正在寻找一些系统修复而不是解决方法(例如使用不同的变量而不是i哪个有效)

我还检查了生成的汇编代码,似乎在 VS2013 中它使用整个 128 位注册表在一个分区中执行 4 个浮点操作。在 VS2015 中,它似乎只执行了 2 个浮点操作,而注册表的其余部分为零(或一些垃圾),这可能会引入此异常。

导致异常的指令如图所示。

VS2013 VS2013

和VS2015 在此处输入图像描述

任何帮助将不胜感激。谢谢。

4

1 回答 1

1

这看起来是使用浮点异常与您进行交互,但也启用了一些浮点优化。

代码所做的是一次执行 2 次迭代(循环展开),但使用一次执行 4 次除法的 divps(来自 XMM 寄存器中的 4 个浮点数)。XMM 寄存器中的高 2 个浮点数未使用,为零。由于未使用这些插槽中的值除法,因此通常无关紧要。但是,当您设置自定义异常处理时,这会引发您看到的无效操作异常,即使它生成的值不会被使用。

正如我所看到的,您的选择是设置 /fp:strict 它将禁用优化,因此使其工作(但它显然会使代码变慢)或删除 controlfp 调用。

于 2016-10-11T10:46:33.647 回答