首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TList中的内存泄漏

TList中的内存泄漏
EN

Stack Overflow用户
提问于 2015-11-11 04:47:43
回答 1查看 456关注 0票数 1

在使用TList时,我遇到了内存泄漏问题。我正在尝试通过填充的列表填充Tlist循环,并使用数据。下面的代码只是用于填充列表的代码,而不是使用它。

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

发布于 2015-11-11 05:19:42

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

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

看起来ClearTList也有同样的缺陷。

您将指针存储在TList实例中,而此类型存储非类型化指针。在释放每个项时,必须将该项强制转换回适当的指针类型,以便运行库知道如何释放记录中的字段。因此,您对Dispose的调用将如下所示:

代码语言:javascript
复制
Dispose(PrintPointer(List[I]));

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

总结一下:

非托管类型的

  • 使用GetMem/FreeMemNew/Dispose。托管类型的
  • 使用New/Dispose
  • 始终将这些函数正确配对。Always FreeMem with GetMem,always Dispose with GetMem
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33639319

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档