3

I came across a strange typo in one of our C++ applications the other day that triggered the code to enter an infinite loop. At the end of a for loop, instead of just incrementing i++, the programmer accidentally assigned i = i++.

for (int i = 0; i < 10; i = i++) {
    cout << "i = " << i << endl;
}

output:

i = 0
i = 0
i = 0
...

The strangest part of this, is that even understanding that this was a typo, I cannot see why this code would not work. As far as I can tell, assigning to i should have no impact because i should still be incremented after the assignment. (For some reason it must instead be incrementing a copy? That doesn't seem to make sense though.)

Another interesting thing to note is changing the assignment to i = ++i will not produce an infinite loop.

This code did not produce an infinite loop on our previous compiler: gcc version 4.4.7 20120313. We recently upgraded to gcc version 4.8.5 20150623 and now it does.

The question is why does this code produce an infinite loop when logically it looks like it shouldn't, and which compiler is interpreting this correctly according to the C++ standard?

tjwrona1992
  • 8,614
  • 8
  • 35
  • 98
  • 4
    I know this is in many ways a duplicate to the canonical "UB and sequence points" (I've already hammered one today), but this one is particularly well-asked. – Bathsheba Sep 27 '18 at 15:47
  • 1
    @Bathsheba It's okay to have well asked duplicates. They will act as sign post for future searchers – NathanOliver Sep 27 '18 at 15:48
  • @NathanOliver: Yes, I'm inclined to agree. The question title alone is very searchable. Appears in Google already! – Bathsheba Sep 27 '18 at 15:49

1 Answers1

6

The behaviour of i = i++ is undefined (simultaneous read write in an unsequenced step - and that is in the standard). Never use it.

Note that i = ++i is defined from C++11.

As for thinking in terms of compiler bugs. It's not impossible that you'll find one, but it's extremely unlikely, particularly if the suspected expression is so small.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483