Rectangle 27 1

infinite loop Is while(1); undefined behavior in C?


a = 1; while(a) while(1);
a = 1; while(a);
int f(unsigned int n, int *a)
{       unsigned int i;
        int s;

        s = 0;
        for (i = 0; i < n-9; i++)
        {
                s += a[i+10];
        }
        return s;
}

Why this clause is not practical

@undefinedbehaviour I just downloaded n1570 and it still has the version in my quote of the clause, where an exception is made for "whose controlling expression is not a constant expression". But as I argue above, it doesn't really help.

Ah. I hadn't noticed that addition. Very well. The one you're looking at is the most current C11 standard draft.

An iteration statement whose controlling expression is not a constant expression,156) that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate.157)

However for the following loop the behavior is unclear

I'm looking at n1570, too, and I assure you that paxdiablo's quote is there, at the end of the page numbered 150 (168 in Adobe Reader page numbers)...

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.

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.

It is well defined behavior. In C11 a new clause 6.8.5 ad 6 has been added

Note that it is essential that n and i are unsigned as overflow on signed int gives undefined behavior and thus the transformation can be justified for this reason. Efficient code however benefits from using unsigned, apart from the bigger positive range.

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 to main. If you really want the infinite loop, you'd better read or write some volatile variable in it.

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.

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.

The compiler is already forced to keep track of whether a propagated constant is a constant expression for other reasons. For instance, sizeof(*(char (*)[1])a++) does not increment a, but sizeof(*(char (*)[non_constexpr_1])a++) does.

The intention of the clause is to allow compiler writers to apply desirable transformations like the following. Consider a not so uncommon loop:

There is however another snag, consider the following code:

Without clause 6.8.5 ad 6 this is not possible, because if n equals UINT_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
Rectangle 27 1

infinite loop Is while(1); undefined behavior in C?


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.

An iteration statement causes a statement called the loop body to be executed repeatedly until the controlling expression compares equal to 0.

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 full text of the paragraph describing the semantics of the iterating statements is:

Note
Rectangle 27 1

infinite loop Is while(1); undefined behavior in C?


a = 1; while(a) while(1);
a = 1; while(a);
int f(unsigned int n, int *a)
{       unsigned int i;
        int s;

        s = 0;
        for (i = 0; i < n-9; i++)
        {
                s += a[i+10];
        }
        return s;
}

Why this clause is not practical

@undefinedbehaviour I just downloaded n1570 and it still has the version in my quote of the clause, where an exception is made for "whose controlling expression is not a constant expression". But as I argue above, it doesn't really help.

Ah. I hadn't noticed that addition. Very well. The one you're looking at is the most current C11 standard draft.

An iteration statement whose controlling expression is not a constant expression,156) that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate.157)

However for the following loop the behavior is unclear

I'm looking at n1570, too, and I assure you that paxdiablo's quote is there, at the end of the page numbered 150 (168 in Adobe Reader page numbers)...

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.

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.

It is well defined behavior. In C11 a new clause 6.8.5 ad 6 has been added

Note that it is essential that n and i are unsigned as overflow on signed int gives undefined behavior and thus the transformation can be justified for this reason. Efficient code however benefits from using unsigned, apart from the bigger positive range.

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 to main. If you really want the infinite loop, you'd better read or write some volatile variable in it.

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.

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.

The compiler is already forced to keep track of whether a propagated constant is a constant expression for other reasons. For instance, sizeof(*(char (*)[1])a++) does not increment a, but sizeof(*(char (*)[non_constexpr_1])a++) does.

The intention of the clause is to allow compiler writers to apply desirable transformations like the following. Consider a not so uncommon loop:

There is however another snag, consider the following code:

Without clause 6.8.5 ad 6 this is not possible, because if n equals UINT_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