Comment by teo_zero
7 hours ago
Take this example:
for (i=0;i<n;i++)
A[i]=0;
for (i=0;i<n;i++)
B[i]=0;
It can be conveniently transformed into this:
for (i=0;i<n;i++)
A[i]=B[i]=0;
They are exactly equivalent except if the first loop never terminates.
Now, the compiler could try to understand if the first loop does or doesn't terminate, and apply or not the optimization accordingly, but Turing tought us that is indeed a hard task!
Or it could decide to never apply it, for fear of those rare and usually pathological cases where the first loop doesn't terminate.
Or it could decide to apply it by default and accept that in those cases the program does something different than what the source code says. The latter is better known as UB.
The third option won, and that's why infinite loops are UB in the standard.
You might ask why it's important that the first loop terminates since in this case the extra side effect would just be a dead store - but if the first loop doesn't terminate then it's possible B is an invalid pointer and then accessing it during the first loop is UB when it shouldn't be. Making a nonterminating loop UB is the patch for this.
The standard example is a linked list instead of an array because the compiler can't prove it never has a cycle.