It is All about Traffic, and Programming
Search
Archives
0 visitors online now
0 guests, 0 members

Who touches my “for-loop” condition?

This post has already been read 93 times!

A for loop is a common control structure that allows repetitions of certain statements for a specific number of times. The syntax of a for-loop in C++ or C# is

for (initialization; condition; increment) {
   statement(s);
}

As simple as ABC. As easy as a no-brainer. As happy as Clam.

Now, look at the following C++ code. How many times would the the loop execute?

int main( )
{
   int N = 10;

   for ( int i = 0; i < N; i++ ) {
     N--;
     std::cout << "i = " << i 
               << ";"
               << "N= "  << N 
               << std::endl;
   }

   return 0;
} 

As the output shown below – The loop executes 5 times, even though we set N = 10.  Obviously, modifying N inside the loop body, i.e., N–, causes the termination of the loop prematurely.

Generally speaking, it is a bad practice to modify loop termination condition inside a for-loop. Bad, Bad, Bad!

Now, the same question for a similar Delphi code:

uses
  System.SysUtils;

var
  I, N: Integer;

begin
  try
    N := 10;

    for I := 0 to N do
    begin
      Dec(N);
      WriteLn( Format('I=%d, N=%d',[I, N]) );
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

The output is not so much unsurprising – unlike the C++ counterpart, it does loop 11 times:

Interesting. It seems modifying N inside loop body doesn’t impact the number of intended loop execution times.

Let’s check the disassembled C++ binary:

As seen from the highlighted lines, N is referenced by address (i.e., ptr [N]) in loop body. This means, any change to N’s value will eventually impact the termination condition evaluation. Address [ebp-14h] is the local variable i stored in Stack, which is incremented with every repetition of the loop, before comparing to ptr[N] that is decremented with each loop.

Delphi compiler generates something different:

N is addressed at [0x004258a8]. At the beginning of the loop, N’s value is copied to [$ebp-$14]. Each loop just checks [$ebp-$14] for termination. Modifying the original Nwouldn’t impact the loop termination condition evaluation.

So, though it is generally not a good practice to change for-loop termination condition inside the loop,  Delphi obviously has some compiler caveat that may slip the mind of a careless programmer. Be warned!

This post has already been read 93 times!

Leave a Reply

Your email address will not be published. Required fields are marked *