I'm having a little trouble understanding the behaviour of pointers. I have a very simple example to demonstrate:
type
PSL = ^TStringList;
...
var
myPSL : PSL;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
New(myPSL);
myPSL^ := TStringList.Create;
myPSL^.Add('String 1');
myPSL^.Add('String 2');
myPSL^.Add('String 3');
end;
...
procedure TForm1.FormDestroy(Sender: TObject);
begin
Dispose(myPSL);
end;
With this code I get this memory leak report
29 - 36 bytes: UnicodeString x 3
37 - 44 bytes: Unknown x 1
85 - 92 bytes: TStringList x 1
Now, if I call
myPSL^.Free;
before disposing of the pointer, then nothing is reported.
I can't understand why this is happening. I know that calling New() allocates enough memory (based on the type of the pointer) and calling Dispose() takes care for deallocating that same memory, then why do I need Free the pointer as if it was a "real" object?
Thanks!
Class objects are already referenced by pointer. It makes very little sense to define a pointer to a reference type. Just use the type directly:
var
myPSL : TStringList;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
myPSL := TStringList.Create;
myPSL.Add('String 1');
myPSL.Add('String 2');
myPSL.Add('String 3');
end;
...
procedure TForm1.FormDestroy(Sender: TObject);
begin
myPSL.Free;
end;
What your code actually does is following:
New(myPSL)
and Dispose(myPSL)
are simply allocating/deallocating a memory block that is sizeof(TStringList)
bytes in size, but are not actually constructing/destructing the TStringList
object within that memory. You need to call myPSL := TStringList.Create
and myPSL.Free
for that instead.
You do not need to store pointer to TStringList
, instance of TStringList
is actually also pointer. To solve it, change type of myPSL
to something like below:
var
myPSL : TStringList;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
myPSL := TStringList.Create;
myPSL.Add('String 1');
myPSL.Add('String 2');
myPSL.Add('String 3');
end;
...
procedure TForm1.FormDestroy(Sender: TObject);
begin
myPSL.Free;
end;
If somehow, you still need to use your old code, to avoid memory leak, you need to call Free
before you dispose myPSL
:
myPSL^.Free;
dispose(myPSL);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With