Search code examples
c++floating-point-exceptions

"Floating-point invalid operation" when inputting float to a stringstream


I have a simple piece of code that extracts a float from a FORTRAN-generated REAL array, and then inserts it into a stream for logging. Although this works for the first 30 cases, on the 31st it crashes with a "Floating-point invalid operation".

The code is:

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";

When debugging, the value of swap_float the instance before the crash (on the last line, above) is 1711696.3 - other than this being much larger than most of the values up until this point, there is nothing particularly special about it.

I have also tried replacing message_stream with cerr, and got the same problem. I had hitherto believed cerr to be pretty much indestructable - how can a simple float destroy it?

Edit:

Thanks for the comments: I've added the declaration of mrSwap. mrSwap is approximately 200 long, so I'm a long way off the end. It is populated outside of my control, and individual entries may not be populated - but to the best of my understanding, this would just mean that swap_float would be set to a random float?


Solution

  • individual entries may not be populated - but to the best of my understanding, this would just mean that swap_float would be set to a random float?

    Emphatically not. Certain bit patterns in an IEEE floating-point number indicate an invalid number -- for instance, the result of an overflowing arithmetic operation, or an invalid one (such as 0.0/0.0). The puzzling thing here is that the debugger apparently accepts the number as valid, while cout doesn't.

    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.

    Updated again to add: Another possibility is a delayed floating-point trap. The floating-point co-processor (built into the CPU these days) generates a floating-point interrupt because of some illegal operation, but the interrupt doesn't get noticed until the next floating-point operation is attempted. So this crash might be a result of the previous floating-point operation, which could be anywhere. Good luck with that...