Reputation: 29
I am having a memory leak problem when using a TList. I am trying to populate the Tlist loop throught the populated list and use the data. The code below is only the code for populating the list not using it.
private
{ Private Form Variable declarations }
GlblCancel : Boolean;
MyPrintLst : TList;
PrintRecord = record
PrintString1,
PrintString2,
PrintString3,
PrintString4,
PrintString5,
PrintString6 : string;
PrintFloat1,
PrintFloat2,
PrintFloat3 : Double;
end;
PrintPointer = ^PrintRecord;
Procedure TMyForm.Create;
begin
MyPrintLst := TList.Create;
end
Procedure TMyForm.FreeTList(Var List : Tlist; Size : Integer);
Var I, Count : Integer;
begin
Count := list.Count - 1;
For I := Count DownTo 0 Do
FreeMem(List[I], Size);
List.Clear;
List.Free;
end;
Procedure TMyForm.FormClose;
begin
FreeTList(MyPrintLst,SizeOf(PrintRecord));
end
procedure AddToPrintList(PrintList : TList;
Const MyStrings : Array of String;
Const MyDoubles : Array of Double);
var
PrintPtr : PrintPointer;
begin
New(PrintPtr);
IF High(MyStrings) >= 0 Then
PrintPtr^.printString1 := MyStrings[0];
Begin
IF High(MyStrings) >= 1 Then
Begin
PrintPtr^.printString2 := MyStrings[1];
IF High(MyStrings) >= 2 Then
Begin
PrintPtr^.printString3 := MyStrings[2];
IF High(MyStrings) >= 3 Then
Begin
PrintPtr^.printString4 := MyStrings[3];
IF High(MyStrings) >= 4 Then
PrintPtr^.printString5 := MyStrings[4];
Begin
IF High(MyStrings) >= 5 Then
PrintPtr^.printString6 := MyStrings[5];
End; {>=5}
End; {>=4}
End; {>=3}
End; {>=2}
End; {>=1}
IF High(MyDoubles) >= 0 Then
Begin
PrintPtr^.PrintFloat1 := MyDoubles[0];
IF High(MyDoubles) >= 1 Then
Begin
PrintPtr^.PrintFloat2 := MyDoubles[1];
IF High(MyDoubles) >= 2 Then
PrintPtr^.PrintFloat3 := MyDoubles[2];
End;
End;
PrintList.add(PrintPtr);
end;
Procedure TMyForm.Button1.Click;
Var EstReading : LongInt;
begin
EstReading := 0;
ClearTList(MyPrintLst,Sizeof(PrintRecord));
MyQuery.First;
While Not(MyQuery.EOF) Do
begin
EstReading := EstReading + 1;
AddToPrintList(MyPrintLst, [MyQuery.FieldByName('Field1').AsString,
MyQuery.FieldByName('Field2').AsString,
MyQuery.FieldByName('Field3').AsString,
MyQuery.FieldByName*'Field4').AsString,
MyQuery.FieldByName('Field5').AsString,
MyQuery.FieldByName('Field6').AsString],
[EstReading]);
MyQuery.Next;
end;
end
Upvotes: 1
Views: 635
Reputation: 613461
You are not disposing of the dynamically allocated records correctly. You record is managed, since it contain managed types, strings in this case.
Managed types, when allocated dynamically like this, need to be allocated with New
, and deallocated with Dispose
. Your mistake is to use FreeMem
and not Dispose
. The latter will dispose of the managed types within the record, the former does not. Hence your leak.
It seems likely that ClearTList
has the same defect.
You are storing the pointers in a TList
instance, and this type stores untyped pointers. When you dispose of each item you must cast the item back to the appropriate pointer type so that the runtime knows how to dispose of the fields within the record. So your call to Dispose
will look like this:
Dispose(PrintPointer(List[I]));
As an aside, passing the size of the element when calling FreeMem
is rather pointless.
To summarise:
GetMem/FreeMem
, or New/Dispose
. New/Dispose
. FreeMem
with GetMem
, always Dispose
with New
. Upvotes: 12