2015-11-10 3 views
1

У меня проблема с утечкой памяти при использовании TList. Я пытаюсь заполнить цикл 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.
+0

Вызов Clear бессмысленен, если вы уничтожите объект. Передача списка как 'var' бессмысленна, поскольку вы не изменяете переменную. В любом случае, я думаю, я ответил на вопрос, который вы попросили, нет? –

+0

Я изменил freemem в процедуре freetlist и процедуру cleartlist на Dispose, и я все еще получаю утечку памяти. – SCAJason

+0

Я ответил на вопрос, который вы задали. Предположительно, у вас есть другие недостатки. Нечестно ожидать от нас отладки остальной части вашего кода, которую мы не видим. Если бы вы предоставили [mcve], мы могли бы исправить весь код там. Но вы этого не сделали. Кстати, очень странно писать 'Count: = List.Count-1'. Используйте 'Count' для хранения, ну, счет и не меньше, чем счет. Для этого необязательно создавать локальную переменную. Убери это. –