gpt4 book ai didi

delphi - TList 中的内存泄漏

转载 作者:行者123 更新时间:2023-12-03 01:02:43 26 4
gpt4 key购买 nike

我在使用 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

最佳答案

您没有正确处理动态分配的记录。您的记录是托管的,因为它包含托管类型,在本例中为字符串。

托管类型,当像这样动态分配时,需要使用New进行分配,并使用Dispose进行释放。您的错误是使用 FreeMem 而不是 Dispose。后者将处理记录中的托管类型,而前者则不会。因此你的泄漏。

ClearTList 似乎也有同样的缺陷。

您将指针存储在 TList 实例中,并且此类型存储无类型指针。当您处置每个项目时,您必须将项目强制转换回适当的指针类型,以便运行时知道如何处置记录中的字段。因此,您对 Dispose 的调用将如下所示:

Dispose(PrintPointer(List[I]));

顺便说一句,在调用 FreeMem 时传递元素的大小是毫无意义的。

总结一下:

  • 对于非托管类型,请使用 GetMem/FreeMemNew/Dispose
  • 对于托管类型,请使用New/Dispose
  • 始终正确配对这些功能。始终将 FreeMemGetMem 结合使用,始终将 DisposeNew 结合使用。

关于delphi - TList 中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33639319/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com