The Delphi Bug List

Entry No.
129
Compiler - Code generation
When code relies on initial global variable zeroing, the optimizer can get confused and produce bad code
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 4.03 5.0 5.01 6.0 6.01 6.02 Kylix 1.0
N/AExistsExistsExistsExistsExistsExistsExistsExistsExistsExistsExistsExistsExistsExists
Description
Reported by Jani Järvinen; checked by Reinier Sterkenburg
Problem example:
program Project1;

{$OPTIMIZATION ON}

Uses Dialogs,SysUtils;

Var I, J: Integer;

begin
   J := 123;
A: I := I+J;
B: I := J-I; { compiler warning here: "I" not initialized }
               ShowMessage(IntToStr(I));
end.
Above, this simple program should display zero as its result. On statement A, the program relies on the fact that global variables initially have a zero value (I, J both equal zero) and thus the addition is unnecessary and could be an assignment instead (I := J). On B, the code does a substract, and the result should be zero. However, if optimization is on, a garbage result (usually something like -5636096) will occur.

People have questioned where it says that global variables are initialized to zero. Well, on page 47, fourth paragraph of the Language Guide (Delphi 2?) it says: "If a global variable declaration does not explicitly specify an initial value, the memory occupied by the variable will initially be set to zero".
This has been a well-known language feature since BP 7.0, and it is still mentioned in the Delphi 4 on-line help (topic "global variables"). This is also known as "data segment clearing" and will make all non-initialized variables to be set to zero. For example, pointers will be set to nil and strings to empty ('').

Cause:
Because the compiler optimizes the variables to be on CPU registers and not in memory, the register for I is not cleared. If you look at the assembled code, you can see that the EBX register is not cleared and contains a garbage value. The reason for this seems to be the incorrect warning that variable I might not be initialized on statement B (shouldn't the warning occur on statement A?) and thus the optimizer gets confused producing bad code. Stack or memory based variables seem to work OK in this kind of situations.
Solution / workaround
Initialize global variables, even though that is unnecessary:
...
begin
  I := 0; { initialize even if not needed }
  J := 123;
  ...
(Alternative: modify statement A to not to use I: "I := J") Also rearranging or rewriting portions of code seems to help. But until this kind of bugs have been fully documented, the only way to be really sure is to turn optimization off. However, this bug seems to be a special case and should not haunt "normal" Delphi programs.
User-contributed comments
Hallvard Vassbotn
30 Aug 2001  08:04 AM GMT
According to Chief Delphi Architect, Chuch Jazdzewski, this behaviour is as designed, so it should be marked as a gotcha, rather than bug.

In this case, I and J are considered local to the begin..end block that follows and are allocated by the compiler as if they were declared to be local variables of that 'procedure'. If there was a real procedure declaration between the variable declaration and the begin..end, they would be treated as global variables.
Jordan Russell
09 Sep 2001  04:39 PM GMT
The issue here is not that the compiler uses an optimization; that is not a bug. The bug is that the program behaves *differently* with optimization on.

If you look up "$O" in the Delphi documentation, you'll notice:
All optimizations performed by the Object Pascal compiler are guaranteed not to alter the meaning of a program. In other words, Delphi performs no "unsafe" optimizations that require special awareness by the programmer.

I think it's fine that the compiler wants to store certain global variables in registers as an optimization, but for consistency it has to initialize those registers when the program doesn't.
Pete
01 Dec 2002  12:04 AM GMT
I think this bug is a bit weak, surely any serious programmer would initialise a varible before performing mathematic calculations.
Not a serious issue for people like me. (asp coder)
Latest update of this entry: 2002-04-03

Post a comment on this bug


Index page
Delphi Bug List home page
The Delphi Bug Lists are presently maintained by Jordan Russell, who has taken over this task from Reinier Sterkenburg since August 2000.
All feedback is appreciated. See also the feedback section of the Delphi Bug List home page.