The Delphi Bug List

Entry No.
452
Compiler - Code generation
Small objects can give strange runtime errors
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 Björn Sahlen; checked by Reinier Sterkenburg
To reproduce, compile and execute the code below.

This is a bug because:
If there is something wrong with this code (which I don't think it is), the compiler should give an error. Now you will get this message on the screen at runtime:
Project ... raised exeption class EAccessViolation with message 'Access violation at adress ...'

Under Kylix, the behaviour is slightly different: On the statement AObj.Prop:= 3; in TForm1.FormCreate, a SIGSEGV error occurs, followed by an Access Violation.
A closer look (stepping/tracing) reveals that the program jumps spontaneously to the PROCEDURE IObj.Proc and that is where the error occurs.
Note: this happens with Optimization Off.
It seems that somehow there is a mixup with the address of the field (property).

This bug is N/A for Delphi 1 since Delphi 1 does not allow properties in objects.

The code:

unit DelphiErr2U;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

TYPE
  IObj= Object
//  FieldThatMakesTheTotalFieldSizeGreaterThanFourBytes: Byte;
    I: LongInt;
    FUNCTION  Func: LongInt;
    PROCEDURE Proc (X: LongInt);
    PROPERTY  Prop: LongInt  Read Func  Write Proc;
    END;

FUNCTION IObj.Func: LongInt;
BEGIN
  Result:= 5;
END;

PROCEDURE IObj.Proc(X: LongInt);
BEGIN
  I:= X + 1;
END;

procedure TForm1.Button1Click(Sender: TObject);
VAR  AObj: IObj;  Z: LongInt;
begin
  AObj.Prop:= 3;
  Z:= AObj.Prop;
  Caption:= IntToStr(Z);
end;                     //  Access violation when leaving this procedure.

end.
Solution / workaround
The only acceptable workaround for me is to use a record and standard functions and procedures instead of an object. An other workaround is of course to make sure that the size of your objects are at least five bytes
User-contributed comments
Chris R. Timmons
30 Jun 2001  04:56 AM GMT
The example code has two bugs.

First, IObj is declared as an "old-style" object. Borland knows about several bugs associated with classes declared with the object keyword. The declaration for IObj should be "IObj = class", not "IObj = object".

The second bug is in Button1Click. AObj is never instantiated! Of course it will generate Access violations. The code should be something like this:

AObj := IObj.Create;
try
AObj.Prop := 3;
Z := AObj.Prop;
Caption := IntToStr(Z);
finally
AObj.Free;
end;

With these two changes, the code works fine on my system (Delphi 5.01, Win2K SP2).
Jordan Russell
01 Jul 2001  07:04 PM GMT
Actually, old-style objects don't need to be instantiated in any way unless they are declared as pointers (e.g. "AObj: PObj") or contain virtual methods.
Joanna Carter
20 Apr 2002  12:54 PM GMT
The var AObj is not a pointer, it is a variable. In order to access the object you should take the address of the variable, this seems to work under D6.02.

procedure TForm1.Button1Click(Sender: TObject);
var
  AObj: IObj;
  Z: LongInt;
begin
  Iobj(@AObj).Prop:= 3;
  Z := Iobj(@AObj).Prop;
  Caption:= IntToStr(Z);
end; 
AE
15 Feb 2003  11:58 AM GMT
This all does not explain one thing, though: why does the access violation happen deferred - upon exit from procedure, not upon access itself?

This happened to me quite a lot: some side effect (usually involving dynamically allocated strings) causing the debugger to show execution point at weird places in code, make access violations in IDE, and in the worst cases, IDE silently exiting upon the next press of F7. Gives neither any idea of where the problem's origin is, nor allows to trace the code. Exceptionally nasty, and still true in Delphi 6 PE.
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.