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