Date: Thu, 18 Sep 2025 15:44:23 +0200
On 18/09/2025 14:52, Mihail Mihaylov via Std-Discussion wrote:
> On Thu, Sep 18, 2025 at 12:41 PM David Brown via Std-Discussion
> <std-discussion_at_[hidden]
> <mailto:std-discussion_at_[hidden]>> wrote:
>
> C and C++ are defined in terms of observable behaviour.
>
> Yes, and the initial message in this thread is questioning exactly
> observable behavior - whether the program halts, is observable behavior
> even when there are no other side effects. If the program contains a
> loop which the programmer can formally prove to be infinite, then the
> programmer expects to observe that the program never completes. And if
> the compiler optimizes the whole loop away, this leads to observable
> behavior (halting) which is different from what is expected.
Infinite loops are not observable behaviour. There is no way to
distinguish between a loop that continues forever, and one that simply
hasn't ended yet.
And if the standards say that something is UB, then that thing is not
observable behaviour as far as the language is concerned - since the
thing has no meaning, there is no way to tell if it has happened or not.
Of course it is possible to decide that a particular thing (in this
case, an infinite loop) /should/ have a meaning and a distinct
behaviour, either as part of the general observable behaviour or as a
special case. And that is what has been done (or rather, is being done)
in C++26 for trivially infinite loops.
>
> The fact that an infinite loop without side effects needs to be
> designated as UB to allow this optimization further demonstrates that
> the issue concerns observable behavior. If it wasn't observable, there
> would be nothing to define or explicitly leave undefined.
>
At the risk of sounding too philosophical and missing the practical
realities, a do-nothing infinite loop is not in itself observable but it
will block all future observable behaviour of the program. Many (if not
all) cases where the C or C++ standards explicitly say something is
undefined behaviour, could simply have omitted a description and left
the behaviour implicitly undefined. Marking something explicitly as UB
is for clarity.
(I'm not saying that I think UB is a good language choice in this case.
I prefer the way C handles it - if you have a do-nothing loop, the
compiler can elide it as dead code without bothering to check for finite
or infinite looping. The exception is if the controlling expression is
constant - then the programmer is considered to have intended to write a
tight infinite loop, and the compiler generates code accordingly.
There's no UB either way.)
> And so, the issue raised by the initial message is about the pros and
> cons of specifying that this observable behavior is undefined. I myself
> am not competent enough to have a definite opinion, but I wouldn't want
> the discussion to stray too far away and lose sight of this original
> question.
>
I am trying to be as accurate and helpful as I can, but "trying" is not
always the same as "succeeding" :-)
However, as far as I see it, until C++26 such infinite loops were not
observable behaviour in terms of the language. Indeed, UB is never
observable behaviour. (The term "observable behaviour" is, AFAIK, only
actually defined in C - C++ has the same principles in its "forward
progression" requirements.) Of course there are things about a program
that a /user/ can observe that are not part of the language
specification - the run-time of the program, crashes, the size of the
executable, and so on. These are parts of the reality of the program
that users see, but are not behaviour described by the language
standards and its abstract machine. It is sometimes difficult to be
clear about such distinctions (at least, /I/ sometimes find it difficult).
> On Thu, Sep 18, 2025 at 12:41 PM David Brown via Std-Discussion
> <std-discussion_at_[hidden]
> <mailto:std-discussion_at_[hidden]>> wrote:
>
> C and C++ are defined in terms of observable behaviour.
>
> Yes, and the initial message in this thread is questioning exactly
> observable behavior - whether the program halts, is observable behavior
> even when there are no other side effects. If the program contains a
> loop which the programmer can formally prove to be infinite, then the
> programmer expects to observe that the program never completes. And if
> the compiler optimizes the whole loop away, this leads to observable
> behavior (halting) which is different from what is expected.
Infinite loops are not observable behaviour. There is no way to
distinguish between a loop that continues forever, and one that simply
hasn't ended yet.
And if the standards say that something is UB, then that thing is not
observable behaviour as far as the language is concerned - since the
thing has no meaning, there is no way to tell if it has happened or not.
Of course it is possible to decide that a particular thing (in this
case, an infinite loop) /should/ have a meaning and a distinct
behaviour, either as part of the general observable behaviour or as a
special case. And that is what has been done (or rather, is being done)
in C++26 for trivially infinite loops.
>
> The fact that an infinite loop without side effects needs to be
> designated as UB to allow this optimization further demonstrates that
> the issue concerns observable behavior. If it wasn't observable, there
> would be nothing to define or explicitly leave undefined.
>
At the risk of sounding too philosophical and missing the practical
realities, a do-nothing infinite loop is not in itself observable but it
will block all future observable behaviour of the program. Many (if not
all) cases where the C or C++ standards explicitly say something is
undefined behaviour, could simply have omitted a description and left
the behaviour implicitly undefined. Marking something explicitly as UB
is for clarity.
(I'm not saying that I think UB is a good language choice in this case.
I prefer the way C handles it - if you have a do-nothing loop, the
compiler can elide it as dead code without bothering to check for finite
or infinite looping. The exception is if the controlling expression is
constant - then the programmer is considered to have intended to write a
tight infinite loop, and the compiler generates code accordingly.
There's no UB either way.)
> And so, the issue raised by the initial message is about the pros and
> cons of specifying that this observable behavior is undefined. I myself
> am not competent enough to have a definite opinion, but I wouldn't want
> the discussion to stray too far away and lose sight of this original
> question.
>
I am trying to be as accurate and helpful as I can, but "trying" is not
always the same as "succeeding" :-)
However, as far as I see it, until C++26 such infinite loops were not
observable behaviour in terms of the language. Indeed, UB is never
observable behaviour. (The term "observable behaviour" is, AFAIK, only
actually defined in C - C++ has the same principles in its "forward
progression" requirements.) Of course there are things about a program
that a /user/ can observe that are not part of the language
specification - the run-time of the program, crashes, the size of the
executable, and so on. These are parts of the reality of the program
that users see, but are not behaviour described by the language
standards and its abstract machine. It is sometimes difficult to be
clear about such distinctions (at least, /I/ sometimes find it difficult).
Received on 2025-09-18 13:44:27