3

我有一段简单的代码,它从 FORTRAN 生成的 REAL 数组中提取一个浮点数,然后将其插入到流中进行记录。虽然这适用于前 30 个案例,但在 31 日它会因“浮点无效操作”而崩溃。

代码是:

int FunctionDeclaration(float* mrSwap)
{
...
float swap_float;
stringstream message_stream;
...
swap_float = *(mrSwap+30-1);
...
message_stream.clear();
message_stream <<  30 << "\t" << swap_float << "\tblah blah blah \t";

调试时,崩溃前实例的 swap_float 的值(在上面的最后一行)是 1711696.3 - 除了比到目前为止的大多数值大得多之外,它没有什么特别的地方。

我也尝试用 cerr 替换 message_stream,并遇到了同样的问题。迄今为止,我一直认为 cerr 几乎是坚不可摧的——一个简单的浮子怎么能摧毁它?

编辑:

感谢评论:我已经添加了mrSwap的声明。mrSwap 大约有 200 长,所以我离结束还有很长的路要走。它在我的控制之外填充,并且可能不会填充单个条目 - 但据我所知,这只是意味着 swap_float 将设置为随机浮点数?

4

2 回答 2

3

单个条目可能不会被填充 - 但据我所知,这只是意味着 swap_float 将被设置为随机浮点数?

坚决不。IEEE 浮点数中的某些位模式表示无效的数字——例如,溢出算术运算的结果,或无效的结果(例如 0.0/0.0)。这里令人费解的是,调试器显然接受该数字为有效,而cout没有。

Try getting the bit layout of swap_float. On a 32-bit system:

int i = *(int*)&swap_float;

Then print i in hexadecimal, and let us know what you see.

Updated to add: From Mike's comment, i=1238430338, which is 49D0F282 in hex. This is a valid floating-point number, equal to exactly 1711696.25. So I don't know what's going on, I'm afraid. The only thing I can suggest is that maybe the compiler is loading the invalid floating-point number directly from the mrSwap array into the floating-point register bank, without going through swapFloat. So the true value of swapFloat is simply not available to the debugger. To check this, try

int j = *(int*)(mrSwap+30-1);

and tell us what you see.

再次更新添加:另一种可能性是延迟浮点陷阱。浮点协处理器(这些天内置在 CPU 中)由于某些非法操作而产生浮点中断,但直到尝试下一个浮点操作时才会注意到该中断。所以这个崩溃可能是之前的浮点运算的结果,它可能在任何地方。祝你好运……

于 2012-05-09T11:57:08.547 回答
3

我只是添加此答案以突出显示上述 TonyK 答案中的正确解决方案 - 因为我们做了几个循环,答案已被编辑,并且由于评论中有几个要点,实际答案可能不会立即显现。所有的功劳都应该归功于 TonyK 的解决方案。

“另一种可能性是延迟浮点陷阱。浮点协处理器(这些天内置在 CPU 中)由于某些非法操作而产生浮点中断,但直到下一次浮点时才会注意到中断点操作被尝试。所以这个崩溃可能是之前的浮点操作的结果,它可能在任何地方。- 托尼克

这确实是问题所在:在我使用 IsSame 的比较中,另一个值是 NaN(在这种情况下这是一个有效值),尽管它很高兴地从 swap_float 中减去它,但它在表示将下一个操作报告为错误。我不得不说我完全没有意识到这是可能的——我认为如果它有效,它就会有效。

于 2016-09-02T15:27:05.213 回答