I simplified the following code at the maximum to only show my problem. When the destructor TClass3.Destroy is done, the action FreeAndNil(FClass3) causes a problem and the program stops. If have a look in the Heap.trc file I can read
Marked memory at $0000000001528FD0 invalid
Wrong signature $2951FD2D instead of 5C063D8B
program Project_testFree;
{$mode objfpc}{$H+}
uses
sysutils;
type
TClass1 = class
private
protected
public
constructor Create;
end;
TClass2 = class(TClass1)
private
protected
FTClass2 : cardinal;
public
end;
TClass3 = class
private
protected
FClass3 : TClass1;
public
constructor Create;virtual;
destructor Destroy;override;
end;
TClass4 = class(TClass3)
private
function GetLocalClass2: TClass2;
protected
public
constructor Create;override;
destructor destroy;override;
property pClass2:TClass2 read GetLocalClass2;
end;
constructor TClass1.Create;
begin
inherited;
end;
constructor TClass3.Create;
begin
FClass3 := TClass1.create;
end;
destructor TClass3.Destroy;
begin
FreeAndNil(FClass3);
writeln('Destroy');
inherited Destroy;
end;
constructor TClass4.Create;
begin
inherited Create;
pClass2.FTClass2 := 1;
end;
destructor TClass4.destroy;
begin
inherited destroy;
end;
function TClass4.GetLocalClass2: TClass2;
begin
result := TClass2(FClass3);
end;
var
c:TClass4;
begin
if FileExists('heap.trc') then
DeleteFile('heap.trc');
SetHeapTraceOutput('heap.trc');
c:=TClass4.Create;
c.free;
end.
I use Lazarus 1.6.2. Thanks for your help.
You cast FClass3
to be TClass2
. But you instantiated TClass1
. The cast is therefore incorrect which would explain the error. Essentially, you lied to the compiler and it exacted its revenge.
Had you used a checked cast, using as
, then a runtime error would have been raised.