使用TList时出现内存泄漏问题。我试图填充填充列表中的Tlist循环并使用数据。下面的代码只是用于填充不使用它的列表的代码。
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
答案 0 :(得分:12)
您没有正确处理动态分配的记录。您的记录是受管理的,因为它包含托管类型,在这种情况下为字符串。
当像这样动态分配时,托管类型需要使用New
进行分配,并使用Dispose
取消分配。您的错误是使用FreeMem
而不是Dispose
。后者将在记录中处理托管类型,前者不会。因此你的泄漏。
ClearTList
似乎有相同的缺陷。
您将指针存储在TList
实例中,此类型存储无类型指针。处理每个项目时,必须将项目转换回适当的指针类型,以便运行时知道如何处理记录中的字段。因此,您对Dispose
的调用将如下所示:
Dispose(PrintPointer(List[I]));
另外,在调用FreeMem
时传递元素的大小是没有意义的。
总结:
GetMem/FreeMem
或New/Dispose
。 New/Dispose
。 FreeMem
GetMem
,Dispose
始终New
。