In C++11 is it Undefined Behavior, but is it the case in C that while(1);
is Undefined Behavior?
相关问题
- Multiple sockets for clients to connect to
- What is the best way to do a search in a large fil
- glDrawElements only draws half a quad
- How to stop infinite loop in JShell / Kulla?
- Index of single bit in long integer (in C) [duplic
It is well defined behavior. In C11 a new clause 6.8.5 ad 6 has been added
Since the controlling expression of your loop is a constant, the compiler may not assume the loop terminates. This is intended for reactive programs that should run forever, like an operating system.
However for the following loop the behavior is unclear
In effect a compiler may or may not remove this loop, resulting in a program that may terminate or may not terminate. That is not really undefined, as it is not allowed to erase your hard disk, but it is a construction to avoid.
There is however another snag, consider the following code:
Now since the compiler may assume the outer loop terminates, the inner loop should also terminate, how else could the outer loop terminate. So if you have a really smart compiler then a
while(1);
loop that should not terminate has to have such non-terminating loops around it all the way up tomain
. If you really want the infinite loop, you'd better read or write somevolatile
variable in it.Why this clause is not practical
It is very unlikely our compiler company is ever going to make use of this clause, mainly because it is a very syntactical property. In the intermediate representation (IR), the difference between the constant and the variable in the above examples is easily lost through constant propagation.
The intention of the clause is to allow compiler writers to apply desirable transformations like the following. Consider a not so uncommon loop:
For architectural reasons (for example hardware loops) we would like to transform this code to:
Without clause 6.8.5 ad 6 this is not possible, because if
n
equalsUINT_MAX
, the loop may not terminate. Nevertheless it is pretty clear to a human that this is not the intention of the writer of this code. Clause 6.8.5 ad 6 now allows this transformation. However the way this is achieved is not very practical for a compiler writer as the syntactical requirement of an infinite loop is hard to maintain on the IR.Note that it is essential that
n
andi
areunsigned
as overflow onsigned int
gives undefined behavior and thus the transformation can be justified for this reason. Efficient code however benefits from usingunsigned
, apart from the bigger positive range.An alternative approach
Our approach would be that the code writer has to express his intention by for example inserting an
assert(n < UINT_MAX)
before the loop or some Frama-C like guarantee. This way the compiler can "prove" termination and doesn't have to rely on clause 6.8.5 ad 6.P.S: I'm looking at a draft of April 12, 2011 as paxdiablo is clearly looking at a different version, maybe his version is newer. In his quote the element of constant expression is not mentioned.
The following statement appears in
C11 6.8.5 Iteration statements /6
:Since
while(1);
uses a constant expression, the implementation is not allowed to assume it will terminate.A compiler is free to remove such a loop entirely is the expression is non-constant and all other conditions are similarly met, even if it cannot be proven conclusively that the loop would terminate.
After checking in the draft C99 standard, I would say "no", it's not undefined. I can't find any language in the draft that mentions a requirement that iterations end.
The full text of the paragraph describing the semantics of the iterating statements is:
I would expect any limitation such as the one specififed for C++11 to appear there, if applicable. There is also a section named "Constraints", which also doesn't mention any such constraint.
Of course, the actual standard might say something else, although I doubt it.
The simplest answer involves a quote from §5.1.2.3p6, which states the minimal requirements of a conforming implementation:
If the machine code fails to produce the observable behaviour due to optimisations performed, then the compiler isn't a C compiler. What is the observable behaviour of a program that contains only such an infinite loop, at the point of termination? The only way such a loop could end is by a signal causing it to end prematurely. In the case of
SIGTERM
, the program terminates. This would cause no observable behaviour. Hence, the only valid optimisation of that program is the compiler pre-empting the system closing the program and generating a program that ends immediately.One possibility is that a signal is raised and longjmp is called to cause execution to jump to a different location. It seems like the only place that could be jumped to is somewhere reached during execution prior to the loop, so providing the compiler is intelligent enough to notice that a signal is raised causing the execution to jump to somewhere else, it could potentially optimise the loop (and the signal raising) away in favour of jumping immediately.
When multiple threads enter the equation, a valid implementation might be able to transfer ownership of the program from the main thread to a different thread, and end the main thread. The observable behaviour of the program must still be observable, regardless of optimisations.