1

ソフトウェアにメモリ リークがあるかどうかを調べています。そのため、メモリリークの可能性を見つけるために、さまざまなツールやプログラムを使用してきました。私が使用したソフトウェアの 1 つは AQTime でした。Delphi XE に付属していたので、これは単なるデモでした。そのため、そこから有益な情報を得ることができませんでした。そこで、フリーソフト MemProof を使うことにしました。これまでのところ、注意が必要なソフトウェアに関する多くの問題が示されています。そのうちの1つはエラーです。

MemProof を使用してプログラムを開始するとすぐに、ユニット ファイル system.pas から存在しないオブジェクトを破棄しようとしている 2 つのエラーが表示されます。そのため、実際に TObject.Free プロシージャ内にブレーク ポイントを配置すると、プログラムが完全に開始される前にブレーク ポイントが壊れてしまいます。system.pas の Free の手順を実行すると、TIconimage が自分自身を破棄または解放しようとしていることがわかりました。つまり、フリー プロシージャは、実際に起動する前にプログラム内から呼び出されることはありません。

実際の無料の手順は次のとおりです。

procedure TObject.Free;
begin
  if Self <> nil then
    Destroy;
end;

その観察の後、ブレークポイントを削除し、プログラムを最後まで実行させました。プログラムのメイン ウィンドウがポップアップし、ユーザー入力の準備が整いました。ただし、プログラムの WINDOW の一部が画面に表示されると、TObject.Free プロシージャがノンストップで呼び出されることもわかりました。私はそれをまったく理解していません。何故ですか?誰でも説明できますか?TForm が画面に表示されるとプロシージャが常に呼び出されるため、TForm は TObject.Free とどのように関連していますか?

前もって感謝します。

4

3 に答える 3

11

が頻繁に実行される理由についてTObject.Freeは、オブジェクトが破棄されるたびに、任意のオブジェクト、そのメソッドが呼び出されます。すべてのクラスは共通の祖先である TObject から派生します。そのため、Delphi プログラムのほとんどすべてのアクションには、多数のオブジェクトの作成/破棄のペアが含まれ、その結果、TObject.Free.

メモリ リークの検出に関しては、これを解決するために必要なすべてが Delphi に組み込まれています。FastMM メモリ マネージャは、「レポート メモリ リーク」モードで実行でき、リークしているメモリを大量に診断します。

次の簡単なプログラムを考えてみましょう:

program Leaker;
begin
  ReportMemoryLeaksOnShutdown := True;
  TObject.Create;
end.

これにより、次の出力が得られます。

ここに画像の説明を入力

アプリのどこかで Trueに設定する必要があるだけReportMemoryLeaksOnShutdownです (.dpr ファイルの先頭は、どの場所よりも適切です)。

レポートでより多くの情報を受け取りたい場合は、FastMM のフル バージョンをダウンロードして、心ゆくまで設定することができます。

次に、次のような出力が得られます。

A memory block has been leaked. The size is: 84

This block was allocated by thread 0x1304, and the stack trace (return addresses) at the time was:
40455E [System][System.@GetMem]
405A2F [System][System.TObject.NewInstance]
40602E [System][System.@ClassCreate]
4474C2 [Classes][Classes.TStringList.Create]
C275A3 [Main.pas][Main][Main.TMainForm.CreateAuxiliaryForms][997]
C84C8A [OrcaFlex.dpr][OrcaFlex][OrcaFlex.OrcaFlex][351]
75E633CA [BaseThreadInitThunk]
77519ED2 [Unknown function at RtlInitializeExceptionChain]
77519EA5 [Unknown function at RtlInitializeExceptionChain]

The block is currently used for an object of class: TStringList

本当に素晴らしいです。リークしているメモリが Main.pas の 997 行目に割り当てられていることがわかります。まさにそこに意図的なリークを配置しました。

于 2011-03-16T21:28:36.727 に答える
2

ご存知のように、プロジェクト オプションのアプリケーション設定で割り当て可能TApplicationIconプロパティがあります。このプロパティはFIcon、オブジェクトのコンストラクタで作成される TApplication のフィールドに反映されApplicationます。コンストラクターで作成される実際の画像を表すフィールドTIconがあります。TIconImageアプリケーション オブジェクトがプロジェクト リソース ファイルからアイコンをロードして割り当てるとき、リークを防ぐために、この最初の 'TIconImage' を解放する必要があります。Application.InitializeApplication オブジェクトは「controls.pas」の初期化セクションから構築されるため、これはすべてプロジェクト ソースで呼び出される前に発生します。

アプリケーションの起動中または実行中は、多くのことが起こっています。起動時に、ストリーミング メカニズムによってオブジェクト (リソース ストリーム、リーダー、クラス ファインダー、コンポーネント リストなど) が作成され、解放されます。空白の VCL フォーム (コントロールがない) を実行すると、アクティブになるたびにリストが作成され、フォーカスを配置するコントロールが検索され、このリストが解放されます。複雑な GUI アプリケーションでは、マウスを何かの上に置いても、さまざまなグラフィックス オブジェクトを作成および解放できます。または、マウスを何かの上に押しても、配置/配置コードはオブジェクトを作成/解放できます。

リークをデバッグするには、David's answerで概説されているコースを受講するか、サードパーティ製品を使用するときに、作成/解放されるすべてのオブジェクトではなく、リークされたものに集中します。:)

于 2011-03-16T22:25:27.513 に答える
0

TObject.Freeは、Delphi のクラスの任意のインスタンスがFreeされるたびに呼び出されます。

これには、単に Delphi プログラムの通常の実行の一部として作成および破棄されるオブジェクトのホスト全体が含まれます。これには、単にウィンドウ オブジェクトを維持するためにシステムによって生成されたメッセージに応答して、TFormオブジェクトによって自動的に処理されるイベントに応答する場合が含まれます。それ自体がWindows独自のWindow Managerに存在します。

たとえば、TCustomForm WndProcから抜粋した次のコード フラグメントについて考えてみましょう。

      WM_MEASUREITEM:
      begin
         :
                Canvas := TControlCanvas.Create;
                with Canvas do
                try
                  :
                finally
                  Canvas.Free;
                end;
        :
      end;

ここで重要なのは、WM_MEASUREITEMメッセージに応答して、カスタム フォーム (つまり、最終的にTCustomFormから派生するため、標準のTForm派生クラス) が一時的なTControlCanvasを作成し、それが完了するとFreeになるということです。

これは、特定のフォームのケースで見られるTObject.Free呼び出しのソースであるとは限りません。これは単なる例ですが、TFormが単に存在するだけで、他のオブジェクトが存在し、それに応答して破棄される可能性があることを示しています。自動のシステム生成メッセージ。

于 2011-03-17T02:54:55.300 に答える