8

いくつかのフォームを備えたアプリケーションがあり、開始時に1つのデータモジュールのみが作成されたとします。DM1.OnCreateイベントでは、実行時に使用するためにaがTStringList作成されます。アプリケーションが終了すると、すべてのものが破棄され、メモリが自動的に解放されることがわかっています。何かを解放するには時間がかかることがあるため、シャットダウン時のメモリリークについて常に心配することをお勧めします。たとえば、Barry Kellyからのこの回答、またはRaymondChenからのこの投稿を参照してください。

TStringList.Freeそれに加えて、に追加しない場合、FastMMはメモリリークを報告しますDM1.OnDestroyこれは、私が本当に心配すべき他のメモリリークを検索するときに問題になることがわかりました。

したがって、基本的には、アプリケーションまたはOS(この特定のケースではWindows)によって解放されるオブジェクトインスタンスを解放する必要があるかどうか、なぜ、いつ解放する必要があるかを尋ねています。メモリリークを探すときにない他の有効なケースはありますか?

:この特定のケースでは、データモジュールは何度も作成または再作成されません。1つを除いて、メモリリークはまったくありません。データモジュールのスクラップソース:

unit UDM1;

interface

uses SysUtils, Classes, ...;

type
  TDM1 = class(TDataModule)
    procedure DataModuleCreate(Sender: TObject);
    procedure DataModuleDestroy(Sender: TObject);
    procedure DoStuffWithStringList1(Sender: TObject);
  private
    internalStL: TStringList;
  end;

var
  DM1: TDM1;

implementation

procedure TDMInterfacePAFECF.DataModuleCreate(Sender: TObject);
begin
  internalStL := TStringList.Create();
end;

procedure TDMInterfacePAFECF.DataModuleDestroy(Sender: TObject);
begin
  internalStL.Free; //<-- IS THIS NECESSARY OR ADVISED?
end;

procedure DoStuffWithStringList(Sender: TObject);
begin
  //Place some code using internalStL here...

end;
4

5 に答える 5

7

私の答えは哲学的と見なすことができますが、主な理由は、行動(または行動の欠如)が結果をもたらすことです。私はあなたの例とおそらく他の例について考えました、そして私はオブジェクトを解放する1つの正当な理由を見ます。オブジェクトの解放を無視できると思うたびに、他の、おそらくもっと深刻な状況でこれを行わない可能性が高くなります。もう1つの例は、何かが割り当てられたり解放されたりするすべての場所で「最後に終了する」ことを行う習慣です。例外が発生した場合の解放は気にしませんが、この習慣は漏れを防ぐのに役立ちます

于 2012-03-27T19:05:44.147 に答える
7

同じ理由で、私はプロジェクトにコンパイラのヒントや警告を残さないことを強く推奨します(控えめな表現)。自分の後できれいにし、報告されたメモリリークを残さないでください!
これまで!

さて、それは必ずしもあなたがそれをしないという強いケースがあるならあなたがあなたのデータモジュールのデストラクタですべてを解放しなければならないことを意味しません、しかしその場合、あなたはそれが報告されないようにあなたのメモリリークを登録する必要があります。(そして、その理由を正当化して説明するために、非常に目に見えるコメントをそこに置いてください)

しかし、あなたがこのプロジェクトを離れて1年後、他の誰かがそれを維持し、複数のDataModuleを作成するための新しいビジネス要件を持っているという事実を考慮してください...彼らがあなたのコードの内部を十分に知らない場合、彼らはあなたのコードがクリーンであると信頼し、問題が続く可能性があります。

したがって、非常に特別で予想され、文書化された場合を除いて、解放しないことを強くお勧めします...

PS:それを見て、あちこちに滴り落ちるメモリを何度も掃討しなければならなかったので、メモリリークと戦うためにCodeRageセッションをいくつか行いました...

Updayte:そのCodeRageセッションをダウンロードするためのリンクは次のとおりです...

于 2012-03-27T19:29:23.310 に答える
5

RegisterExpectedMemoryLeak意図的なメモリリークに使用します。ルーチンにはいくつかのオーバーロードされたバージョンがあり、そのうちの1つをオブジェクトクラスと組み合わせることができます。

begin
  RegisterExpectedMemoryLeak(TStringList);
  FStringList := TStringList.Create;
  ...

以上の場合、ポインタ自体を登録します。

begin
  FStringList := TStringList.Create;
  RegisterExpectedMemoryLeak(FStringList);
  ...

この場合、予期しないメモリリークが正常に発生し、この特定の文字列リストと混同することはできません。

于 2012-03-27T19:22:25.017 に答える
4

質問してお答えします。

データモジュールのライフサイクルは常にアプリケーションのライフサイクルに関連付けられている、または追加のインスタンスを作成する必要がないことを確信できますか?

「はい」と答えた場合は、標準のメモリ管理方法を無視してかまいません。

「いいえ」と答えた場合は、オブジェクトがクリーンアップされていることを確認する必要があります。

于 2012-03-27T18:59:54.967 に答える
2

オブジェクトを解放すると、メモリの割り当てを解除するだけで、作業が完了します。

トランザクションを実行し、ondestroyで開始されたすべてのトランザクションを終了するデータベースオブジェクトを思い浮かびます。

無料で電話をかけないと、ondestroyが解雇されず、テーブルがロックされてしまう可能性があります。

于 2012-03-28T08:44:17.047 に答える