我在从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次浮点运算,其余的注册表为零(或一些垃圾)可能会引入此异常。
引起异常的指示在图中标出。
任何帮助将不胜感激。 感谢。
答案 0 :(得分:1)
这看起来是使用浮点异常与您进行交互,但也启用了一些浮点优化。
代码正在做的是它一次进行2次迭代(循环展开),但是使用divps,它同时进行4次除法(来自XMM寄存器中的4次浮点数)。 XMM寄存器中的上2个浮点数未使用,为零。由于没有使用这些插槽中的值的除法,因此它通常不重要。但是,当您设置自定义异常处理时,这会引发一个无效的操作异常,即使它的生成值不会被使用,也会看到它。
正如我所看到的那样,您的选择是设置/ fp:strict,这将禁用优化,因此使其工作(但显然会使代码变慢)或删除controlfp调用。