我目前在使用VC++ 11(CTP更新1版)编译x86目标时,遇到了随机浮点错误。请参见下面的简短示例“test.cpp”,并使用以下方式进行编译:
cl /GL /O2 /EHsc test.cpp /link /MACHINE:X86
输出应该是
10 == 10
,但当启用/GL
(整个程序优化)时,它会产生10 == 0
。问题似乎是get_scaling_factor()
将结果推送到浮点堆栈上,但调用函数期望在SSE寄存器XMM0中得到结果。
问题:我是否遗漏了一些明显的东西,还是这真的是一个bug?当然,测试程序没有意义,因为它只是一个简化的测试案例。
test.cpp:
#include <iostream>
template <typename T>
inline T get_scaling_factor(int units)
{
switch (units)
{
case 0: return 1;
case 1: return 10;
case 2: return 100;
case 3: return 1000;
case 4: return 10000;
case 5: return 100000;
case 6: return 1000000;
case 7: return 10000000;
case 8: return 100000000;
case 9: return 1000000000;
default: return 1;
}
}
template <int targetUnits, typename T>
inline T scale(T value, int sourceUnits)
{
return value * get_scaling_factor<T>(sourceUnits)
/ get_scaling_factor<T>(targetUnits);
}
__declspec(noinline)
double scale(double value, int units)
{
return scale<9>(value, units);
}
int main()
{
std::cout << "10 = " << scale(1e9, 1) << std::endl;
}
更新
微软已确认问题。即使是像这样简单的代码也会受到影响:
#include <stdio.h>
double test(int a)
{
switch (a)
{
case 0: return 1.0;
case 1: return 10.0;
case 2: return 100.0;
case 3: return 1000.0;
case 4: return 10000.0;
case 5: return 100000.0;
case 6: return 1000000.0;
case 7: return 10000000.0;
case 8: return 100000000.0;
case 9: return 1000000000.0;
default: return 1.0;
}
}
void main()
{
int nine = 9;
double x = test(nine);
x /= test(7);
int val = (int)x;
if (val == 100)
printf("pass");
else
printf("fail, val is %d", val);
}
T
,你会使用static_cast
吗? - Steve-oT(...)
中,它也会失败。而且这也不必要,编译器会将它们提升到正确的类型(如果可以的话)。请注意,即使在最高警告级别下,该代码也可以编译而不产生警告。 - Daniel Gehriger