Hi!
I know that it will be obvious for real C++-masters, but for me it is small surprise. I used to think that signed overflow in C ++ does not cause real undefined behavior on a particular platform. That is, it is clear that depending on the big-endianness/little-endian result may be different.
I found short and funny example:
#include <iostream>
int main()
{
for (int i = 0; i < 300; i++)
std::cout << i << " " << i * 12345678 << std::endl;
}
Being compiled with -O2
on modern g++ it will run infinitely. Suddenly, right?
Last sentence is written in russian, on eng interface :(
This is so strange! I tested it on my machine, and it does indeed run infinitely.
It's interesting I believe. Why does that happen?
There is russian explanation from yeputons, so I am just translating:
-Waggresive-loop-optimization option is turned on by -O2,
Optimizer infers that because i*12345678 should never overflow, i will never be higher then 173, which means that i < 300 is always true, so it replaces condition "i < 300" with true.
strange, if you replace endl with '\n' , the code no longer runs infinitely
My take on this is that std::endl flushes cache, so the output operation happens in the cycle, so output is produced within the cycle and is expected to conform to language rules, which means no overflow is expected and optimization works.
If do you "\n", cache is flushed after the cycle ends, so there is no external output within the cycle, which somehow turns off optimization.
Strange indeed. It probably takes a guy from g++ development team to tell exactly what happens.
By the way, it looks like it's possible to disable that behavior in GCC with a special key:
-fno-strict-overflow
And sometimes such advanced optimizations even lead to vulnerabilities: http://lwn.net/Articles/342330/
I used "\n" instead of endl and got this:
Then this must me a warning bug. Initially whan I was reading this post I thought that gcc does not produce any warnings about that, but it is not good that warning is produced in one case and is not produced in another case.
I confirmed the difference in warning reporting between
std::endl
and"\n"
with GCC 4.8.1 and 4.8.2 . The bug seems to be fixed in GCC >= 4.9.0, I couldn't test if the fix is included in GCC 4.8.3 — 4.8.5 .Mine:
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)
This is another example of breaking the code with higher optimization when the code is not completely correct, Nicely explained as well. http://stackoverflow.com/questions/36626810/g-optimization-breaks-for-loops