Infinite loop heisenbug: it exits if I add a printout

Instead of

while(current != last);

use something like:

while(fabs(current - last) > tolerence);

where tolerance could be a small number, such as 1.0e-6.


@Skizz's comment gives the likely problem, but to elaborate:

Floating point math is tricky, and, in particular, rounding errors can often arise. A number such as 1/1000.0 (the results of your round call) can't be precisely represented in floating point.

A further complication is that there are tradeoffs between speed on the one hand and consistent, intuitive results on the other. For example, an Intel processor's FPU stores values in an 80-bit extended precision format, while a C/C++ double is typically 64 bits. For performance, a compiler may leave values in the FPU, as 80-bit temporaries, even though this can produce different results than what you'd get if you truncated them to 64 bits.

With your debug statement enabled, current is likely stored to memory, truncating it to 64 bits, which permits a direct comparison with last.

With the debug statement disabled, current is likely an 80-bit value stored in an FPU register, and thus it can never equal last, as long as last is a 64-bit value and they're both trying to store an inexact floating point representation of x/1000.0.

The solution is to use a floating point comparison with some allowed error (because a direct check for equality with floating point is almost never a good idea).

Further notes: I haven't looked at the assembly output to verify that this is the case; you can do this yourself if you want. I'm only able to reproduce the problem if I enable optimizations. You may be able to "fix" the bug by tweaking compiler flags to choose consistency over speed, but the correct solution is to use an inexact comparison instead of a direct check for equality.