0

I had a typo in code recently, that was causing an infinite loop in some cases (but not in all environments, it seems).
It looked like this:

for (std::vector<myString>::iterator iter = myVector.begin(); iter != myVector.end(); ++iter = iter)
{
   ...
}

The typo is the assignment of the iterator to itself. Removing it fixes the issues.

I am wondering what exactly happens during the statement ++iter = iter?
I thought that according to operator precedence, iterator should first be incremented, then assigned to self, but I seem to be missing some steps (otherwise there would not be infinite loops).
My feeling is that it also involves dereferencing of the variable, but I am not sure to completely understand what was happening with this bug.
Also, why did it seem to not cause infinite loops on some platforms?

wip
  • 2,205
  • 3
  • 30
  • 46

1 Answers1

3

according to operator precedence, iterator should first be incremented, then assigned to self

Operator precedence does not determine evaluation order.

If the expression d = (a+b)*c, a, b, c and d can be evaluated in any order. a+b has to be evaluated after a and b, (a+b)*c after both a+b and c, and the result of the assignment after both d and the result of the multiplication, but that's about it.

The same used to be the case with the assignment.

The left-hand side and the right-hand side of the assignment previously could be evaluated in any order. In particular, the following order could be realised:

  • iter is evaluated, resulting in a value we call temp
  • ++iter is evaluated (this doesn't affect temp)
    • this results in incrementing of iter, and the value is the newly-incremented iter rvalue
  • temp is assigned to the iter rvalue evaluated above
  • the net result is iter being unchanged

Another evaluation order also used to be possible.

  • ++iter is evaluated
    • this results in incrementing of iter, and the value is the newly-incremented iter rvalue
  • iter (the right hand side of the assignment) is evaluated again
    • the result is the newly-incremented iter converted to lvalue
  • the assignment takes place, leaving iter incremented as expected.

However C++17 has changed this. Assignment is now evaluated strictly from right to left. This means the first evaluation order is now guaranteed, and the second one is not allowed.

n. 1.8e9-where's-my-share m.
  • 102,958
  • 14
  • 123
  • 225
  • Thank you for the explanations. Maybe adding pseudo-code illustrating the two evaluation orders that used to be possible, would be useful? – wip Nov 20 '18 at 01:02