Miamy
Miamy

Reputation: 51

For-loop variable violates loop bound

Today I have met very strange bug.

I have the next code:

var i: integer;
...
for i := 0 to FileNames.Count - 1 do
begin
  ShowMessage(IntToStr(i) + ' from ' + IntToStr(FileNames.Count - 1));
  FileName := FileNames[i];
  ...
end; 
ShowMessage('all');

FileNames list has one element. So, I consider then loop will be executed once and I see

0 from 0
all

It is a thing I did thousands times :). But in this case I see the second loop iteration when code optimization is switched on.

0 from 0
1 from 0
all

Without code optimization loop iterates right. For the moment I don't know even the direction to move with this issue (and upper loop bound stays unchanged, yes).

So any suggestion will be very helpful. Thanks.

I use Delphi 2005 (Upd2) compiler.

Upvotes: 4

Views: 372

Answers (2)

Miamy
Miamy

Reputation: 51

Ok, it seems to me I solved the problem and can explain it. Unfortunately, I cannot make test to reproduce the bug, and I cannot show the real code, which under NDA. So I must use simplified example again.

Problem is in dll, which used in my code. Consider the next data structure:

type
  TData = packed record
    Count: integer;
  end;
  TPData = ^TData;

and function, which defined in dll:

Calc: function(Data: TPData): integer; stdcall;

In my code I try to proceed data records which are taken from list (TList):

var
  i: integer;
  Data: TData;
begin
  for i := 0 to List.Count - 1 do
  begin
    Data := TPData(List[i])^;
    Calc(@Data);
  end;

and in case when optimization is on I see second iteration in loop from 0 to 0. If rewrite code as

var
  i: integer;
  Data, Data2: TData;
begin
  for i := 0 to List.Count - 1 do
  begin
    Data := TPData(List[i])^;
    Data2 := TPData(List[i])^;
    Calc(@Data2);
  end;

all works as expected.

Dll itself was developed by another programmer, so I asked him to take care about it.

What was unexpected for me - that local procedure's stack can be corruped in so unusual way without access violations or other similar errors. BTW, Data and Data2 variables contains correct values.

Maybe, my experience will be useful to someone. Thanks all who helps me and please sorry my unconscious mistakes.

Upvotes: 0

Tom Brunberg
Tom Brunberg

Reputation: 21045

Considering the QC report referred to by LU RD, and my own experience with D2005, here is a few workarounds. I recall using the while loop solution myself.

1.Rewrite the for loop as a while loop

var
  i: integer;
begin
  i := 0;
  while i < FileNames.Count do
  begin
    ...
    inc(i);
  end;
end;

2.Leave the for loop control variable alone from any other processing and use a separate variable, that you increment in the loop, for string manipulation and FileNames indexing.

var
  ctrl, indx: integer;
begin
  indx := 0;
  for ctrl := 0 to FileNames.Count-1 do
  begin
    // use indx for string manipulation and FileNames indx
    inc(indx);
  end;
end;

3.You hinted at a workaround in saying Without code optimization loop iterates right. Assuming you have optimization on turn it off ( {$O-} ) before the procedure/function and on ( {$O+} ) again after. Note! The Optimization directive can only be used around at least whole procedures/functions.

Upvotes: 3

Related Questions