I realise this is a contrived example but the following code causes a memory leak in Delphi XE2 (and maybe other versions).
type
TTest =record
a :string;
procedure SetA;
end;
procedure TTest.SetA;
begin
a:='Test';
end;
procedure TfrmMain.btGoClick(Sender: TObject);
var
t :TTest;
procedure SetA(const Rec: TTest);
begin
Memo.Lines.Add(IntToStr(NativeInt(@Rec)));
Rec.SetA;
end;
begin
Memo.Lines.Add(IntToStr(NativeInt(@t)));
SetA(t);
if t.a='' then
Memo.Lines.Add('t.a: (empty)')
else
Memo.Lines.Add('t.a: '+t.a);
end;
The source of the memory leak is the setting of a
in TTest.SetA
, the string is never released.
The output of the above is:
1700728
1700688
t.a: (empty)
From this we can see that even though the record parameter is passed as a const
the address of Rec is different from the main variable t
.
Now if I change the record type definition to:
TTest =record
a :string;
a1 :string;
a2 :string;
a3 :string;
procedure SetA;
end;
The output is now:
1700712
1700712
t.a: Test
So the same address of Rec
and t
, also t.a
has been set, also no memory leak.
I have tried to look at the CPU but have a hard time seeing the difference when the dummy a1
, a2
and a3
variables are added.
Obviously all this can be avoided by making the parameter to SetA
a var
parameter, but the reason for this question is to try and understand what the compiler is doing in the two different situations.
So what is going on here?