Updated, see below!
I have heard and read that C++0x allows an compiler to print "Hello" for the following snippet
#include <iostream>
int main() {
while(1)
;
std::cout << "Hello" << std::endl;
}
It apparently has something to do with threads and optimization capabilities. It looks to me that this can surprise many people though.
Does someone have a good explanation of why this was necessary to allow? For reference, the most recent C++0x draft says at 6.5/5
A loop that, outside of the for-init-statement in the case of a for statement,
- makes no calls to library I/O functions, and
- does not access or modify volatile objects, and
- performs no synchronization operations (1.10) or atomic operations (Clause 29)
may be assumed by the implementation to terminate. [ Note: This is intended to allow compiler transfor- mations, such as removal of empty loops, even when termination cannot be proven. — end note ]
Edit:
This insightful article says about that Standards text
Unfortunately, the words "undefined behavior" are not used. However, anytime the standard says "the compiler may assume P," it is implied that a program which has the property not-P has undefined semantics.
Is that correct, and is the compiler allowed to print "Bye" for the above program?
There is an even more insightful thread here, which is about an analogous change to C, started off by the Guy done the above linked article. Among other useful facts, they present a solution that seems to also apply to C++0x (Update: This won't work anymore with n3225 - see below!)
endless:
goto endless;
A compiler is not allowed to optimize that away, it seems, because it's not a loop, but a jump. Another guy summarizes the proposed change in C++0x and C201X
By writing a loop, the programmer is asserting either that the loop does something with visible behavior (performs I/O, accesses volatile objects, or performs synchronization or atomic operations), or that it eventually terminates. If I violate that assumption by writing an infinite loop with no side effects, I am lying to the compiler, and my program's behavior is undefined. (If I'm lucky, the compiler might warn me about it.) The language doesn't provide (no longer provides?) a way to express an infinite loop without visible behavior.
Update on 3.1.2011 with n3225: Committee moved the text to 1.10/24 and say
The implementation may assume that any thread will eventually do one of the following:
- terminate,
- make a call to a library I/O function,
- access or modify a volatile object, or
- perform a synchronization operation or an atomic operation.
The goto
trick will not work anymore!
while(1) { MyMysteriousFunction(); }
must be independently compilable without knowing the definition of that mysterious function, right? So how can we determine if it makes calls to any library I/O functions? In other words: surely that first bullet could be phrased makes no calls to functions. – Seventeenthint x = 1; for(int i = 0; i < 10; ++i) do_something(&i); x++;
intofor(int i = 0; i < 10; ++i) do_something(&i); int x = 2;
? Or possibly the other way, withx
being initialized to2
before the loop. It can telldo_something
doesn't care about the value ofx
, so its a perfectly safe optimization, ifdo_something
doesn't cause the value ofi
to change such that you end up in an infinite loop. – Jacinthemain() { start_daemon_thread(); while(1) { sleep(1000); } }
might just exit immediately instead of running my daemon in a background thread? – Arrivewhile(1)
loop could be moved to before the loop by the compiler. Thewhile(1)
still executes, it just may execute before or after other instructions. The real question is what happens if you throwexit(EXIT_SUCCESS)
after the loop. – Lancewoodsleep
's definition does any I/O calls or if the implementation defines "sleep" as an I/O function itself, the loop in @Gabe's comment cannot be assumed to terminate. – Canardunsigned normalize_lsb(unsigned x) { while(!(x & 1)) x>>=1; return x;}
, and a compiler can ascertain that the return value from some particular call is never used, should a compiler be required to generate code that hangs ifx
is zero? Being able to ignore the value ofx
in cases where the return value isn't used (and use the fact thatx
is ignored to in turn omit code whose sole purpose would be to compute it) is a useful optimization, on compilers whose behavior is limited to cleanly omitting or deferring such loops. – Ceballoswhile(1);
will still run forever in C. – Protraction