1

私は、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 タスク マネージャーを確認したところ、メモリ使用量はクエリ後に減少するのではなく、増加し続けています。

これを修正する方法は?

ありがとう!

4

6 に答える 6

13

最初に nil に設定してからnil 変数TADOQueryを呼び出してリークしています (何もしません)。Free

于 2010-10-27T13:51:06.380 に答える
4
  • Delphi 5 の更新プログラムをインストールしましたか? RTM ADO の実装には問題があることがわかっています。
  • FastMM4 を使用すると、Delphi 5 でも動作し、リークの場所について詳しく知ることができます。
于 2010-10-27T14:20:28.647 に答える
3

Delphi の方法:

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;
于 2011-08-14T00:14:58.673 に答える
2

見積もり:

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

冗談でしょ?最初に変数を nil してから解放しますか? あなたは天才です!:-)

使用する:

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

または、Q はローカル変数であるため、わざわざ nil を割り当てないでください...


しかし、コードを読み直すと、アプリケーションを所有者として使用していることに気付きました。その結果、アプリケーションが解放されると解放されるため、実際にはリークにはなりません。フォームを使用する場合、所有者フォームが解放されると解放されます。
試行すべきことは、このクエリを約 100.000 回呼び出して、メモリを予約し続けているかどうか、または特定のサイズに達するまでメモリを増やしているだけかどうかを確認することです。メモリは将来の ADO 呼び出しのために予約されているため、後者の可能性が高くなります。

于 2010-10-27T14:32:12.173 に答える
0

他の人が指摘したように、finally セクションでは、次のように 2 つのステートメントを逆にする必要があります。

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

または、SysUtils.FreeAndNil(Q) を呼び出すこともできます (Delphi 5 で利用できるかどうかはわかりません)。

それに加えて、TaskManager はとにかくメモリ使用量を決定するためのひどい手段です。Q のメモリを解放しても、Delphi メモリ マネージャが OS にメモリを解放するとは限りません。

于 2010-10-27T14:10:07.207 に答える
0

Arjanjasonpenny、およびWorkShop Alexが言ったように行を逆にすることは別として、 Process Explorerを使用して、プロセスのメモリ (プライベート バイト) の実際の消費量を確認できます。タスク マネージャーは、プロセスのワーキング セットのみを表示するため、このタスクにはあまり適していません。

于 2010-10-27T16:05:16.730 に答える