在使用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发布于 2015-11-11 05:19:42
您没有正确处理动态分配的记录。您的记录是托管的,因为它包含托管类型,在本例中为字符串。
当像这样动态分配时,托管类型需要使用New分配,并使用Dispose释放。您的错误是使用FreeMem而不是Dispose。后者将处理记录中的托管类型,而前者则不会。所以你泄密了。
看起来ClearTList也有同样的缺陷。
您将指针存储在TList实例中,而此类型存储非类型化指针。在释放每个项时,必须将该项强制转换回适当的指针类型,以便运行库知道如何释放记录中的字段。因此,您对Dispose的调用将如下所示:
Dispose(PrintPointer(List[I]));顺便说一句,在调用FreeMem时传递元素的大小是没有意义的。
总结一下:
非托管类型的
GetMem/FreeMem或New/Dispose。托管类型的New/Dispose。FreeMem with GetMem,always Dispose with GetMemhttps://stackoverflow.com/questions/33639319
复制相似问题