Mar*_*dik 4 c++ floating-point
我的程序中有一个非常奇怪的错误.我无法在可重现的代码中隔离错误,但在我的代码中的某个位置有:
double distance, criticalDistance;
...
if (distance > criticalDistance)
{
std::cout << "first branch" << std::endl;
}
if (distance == criticalDistance)
{
std::cout << "second branch" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
在调试构建中一切都很好.只执行一个分支.
但是在发布版本中,所有地狱都会破裂,有时两个分支都会被执行.
这很奇怪,因为如果我添加else条件:
if (distance > criticalDistance)
{
std::cout << "first branch" << std::endl;
}
else if (distance == criticalDistance)
{
std::cout << "second branch" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这不会发生.
请问,这可能是什么原因?我在32位计算机上的Ubuntu 13.10上使用gcc 4.8.1.
EDIT1:
我正在使用预编译器标志
EDIT2:
我不认为这是由内存泄漏引起的.我用valgrind内存分析器分析了发布和调试版本,跟踪了单元化内存并检测了自修改代码,我发现没有错误.
EDIT3:
将声明更改为
volatile double distance, criticalDistance;
Run Code Online (Sandbox Code Playgroud)
使问题消失.这是否证实了woolstar的答案?这是编译器错误吗?
EDIT4:
使用gcc选项-ffloat-store也可以解决问题.如果我理解正确,这是由gcc引起的.
woo*_*tar 14
if (distance > criticalDistance)
// true
if (distance == criticalDistance)
// also true
Run Code Online (Sandbox Code Playgroud)
我之前在自己的代码中看到过这种行为.这是由于存储在内存中的标准64位值与英特尔处理器用于浮点计算的80位内部值不匹配.
基本上,当截断为64位时,您的值相等,但在以80位值测试时,一个稍大于另一个.在DEBUG模式下,值始终存储在内存中,然后重新加载,因此它们总是被截断.在优化模式下,编译器会重用浮点寄存器中的值,并且不会被截断.