Delphi: утечка памяти в TAdoQuery? - PullRequest
       75

Delphi: утечка памяти в TAdoQuery?

1 голос
/ 27 октября 2010

Я развиваюсь как небольшая диабетическая программа с использованием Delphi 5 и ADO.Я делаю маленький запрос, как это:

function GetLowestGlucoseLevel(StartDate:string;EndDate:string): Integer;
var
  Q:TADOQuery;
begin
   try
      Q:=TADOQuery.Create(Application); //Separate unit, owner set to App
      Q.Connection:=dtMod.ADOCon;
      Q.DisableControls;
      Q.Close;
      Q.SQL.Clear;
      Q.SQL.Add('SELECT Min(qGlucose.Glucose) AS MinOfGlucose from qGlucose');
      Q.Parameters[0].Value:=StartDate;
      Q.Parameters[1].Value:=EndDate;
      Q.Open;

      Result:=Q.FieldByName('MinOfGlucose').AsInteger;

      Q.Close;
    finally
      Q:=nil;
      Q.Free; 
    end; 
end;

Запрос выполняется нормально и возвращает результат, как и ожидалось.Однако когда я проверял диспетчер задач Windows, после запроса потребление памяти продолжает расти, а не уменьшаться.

Как это исправить?

Спасибо!

Ответы [ 6 ]

13 голосов
/ 27 октября 2010

Вы пропускаете TADOQuery, сначала устанавливая его равным nil, а затем вызывая Free для переменной nil (которая ничего не делает)

4 голосов
/ 27 октября 2010
  • Вы установили обновления Delphi 5? Реализация RTM ADO известна есть проблемы.
  • Используйте FastMM4, он должен работать с Delphi 5, а также рассказать вам больше о том, где утечки.
3 голосов
/ 14 августа 2011

Дельфийский путь:

function GetLowestGlucoseLevel(const StartDate:string; const EndDate:string): Integer;
var
  Q:TADOQuery;

begin

    Q:=TADOQuery.Create(nil); //(nil) because local use only. Placed before try\finally block 
                              //because if it fails to .create then there would be no object to
                              //.Free 
    try

      Q.Connection := dtMod.ADOCon;

      //------can erase these------
      //Q.DisableControls; //No controls attached so unnecessary
      //Q.Close;           //Q is local and was never opened so no need to close
      //Q.SQL.Clear;       //Q is local and was never filled so no need to clear

      Q.SQL.Add('SELECT Min(qGlucose.Glucose) AS MinOfGlucose from qGlucose');
      Q.Parameters[0].Value:=StartDate;
      Q.Parameters[1].Value:=EndDate;
      Q.Open;

      Result := Q.FieldByName('MinOfGlucose').AsInteger;

      Q.Close;

    finally 

      Q.Free;

      //Q := nil          //not needed because Q's scope is local

    end; 
end;
2 голосов
/ 27 октября 2010

Цитата:

finally
  Q:=nil;
  Q.Free; 
end; 

Ты шутишь, верно? Сначала ноль переменной, а затем освободить его? Ты гений! : -)

Использование:

finally
  Q.Free; 
  Q:=nil;
end; 

Или даже не присваивайте ему значение nil, поскольку Q - локальная переменная ...


Но перечитывая ваш код, я замечаю, что вы используете приложение в качестве владельца. В результате на самом деле это не будет утечка, поскольку она будет освобождена при освобождении приложения. Если вы используете форму, она будет освобождена, когда форма владельца будет освобождена.
Вам следует попытаться вызвать этот запрос около 100 000 раз, чтобы проверить, сохраняет ли он память или просто увеличивает объем памяти до достижения определенного размера. Последнее более вероятно, поскольку память зарезервирована для будущих вызовов ADO.

0 голосов
/ 27 октября 2010

Помимо инвертирования строк как Arjan , jasonpenny и WorkShop Alex , вы можете использовать Process Explorer для просмотра реального потребления памяти (Private Bytes) процесса. Диспетчер задач на самом деле не подходит для этой задачи, поскольку он показывает только рабочий набор процесса.

0 голосов
/ 27 октября 2010

Как отмечали другие, в разделе finally должны быть изменены два оператора, например:

finally
  Q.Free; 
  Q:=nil;  // <- not even necessary since this is a local var
end; 

Или вы можете вызвать SysUtils.FreeAndNil (Q) (если это доступно в Delphi 5, ноконечно).

Кроме того, TaskManager - ужасный инструмент для определения использования памяти в любом случае.Вы можете освободить память для Q, но это не означает, что менеджер памяти Delphi освобождает память для ОС.

...