3

次のようなコードで、Delphi 7 アプリケーション (CLX) でメモリ リークの問題が発生しました。

unit Unit2;

interface

  uses ECRClass, ECR_Text,  SysUtils, Types, Classes, Variants, Math;

  type tLeakClass = class
  private
  fsType : integer;

  public
  fsPrinter : TECR_Class;

  published
  constructor Create (AOwner : TComponent);
  destructor Destroy();
  end;


implementation

   constructor tLeakClass.Create (AOwner : TComponent);
   begin
   fsPrinter := TECR_Text.Create(AOwner);
   end;

   destructor tLeakClass.Destroy();
   begin
     fsPrinter.Free
   end;

end.

fsPrinterメインフォーム(TForm)が閉じた瞬間に解放されても、オブジェクトの結果がリークしました:

unit Unit1;

interface

uses
  SysUtils, Types, Classes, Variants, QTypes, QGraphics, QControls, QForms, 
  QDialogs, QStdCtrls, Unit2;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    tleak : tLeakClass;
  end;

var
  Form1: TForm1;

implementation

{$R *.xfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
     tLeak := tLeakClass.Create(Self);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
   tleak.Free
end;

end.

FastMM4 によるリークのレポートは次のとおりです。

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

This block was allocated by thread 0xBA8, and the stack trace (return addresses) at the time was:
402F1C [system.pas][System][@GetMem][2439]
403C77 [system.pas][System][TObject.NewInstance][8360]
404012 [system.pas][System][@ClassCreate][9019]
502F15 [ECR_Text.pas][ECR_Text][TECR_Text.Create][101]
403C80 [system.pas][System][TObject.NewInstance][8360]
404012 [system.pas][System][@ClassCreate][9019]
5030C6 [Unit2.pas][Unit2][tLeakClass.Create][24]
43856C [QStdCtrls.pas][QStdCtrls][2863]
503300 [Unit1.pas][Unit1][TForm1.Button1Click][30]
447076 [QControls.pas][QControls][TControl.Click][1977]
43858C [QStdCtrls.pas][QStdCtrls][TButton.Click][2871]

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

ここで、問題を表すプロジェクトの完全なSSCCEサンプルをダウンロードできます(サンプルを実行するには、ボタンをクリックしてフォームを閉じます)。

fsPrinterオブジェクトがリークするのはなぜですか? どうすればリークを回避できますか?

4

1 に答える 1

6

デストラクタが正しく宣言されていません。あなたが書いた:

destructor Destroy();

ただし、 で宣言されている仮想デストラクタをオーバーライドする必要がありますTObjectFreeそうしないと、で宣言された仮想デストラクタを呼び出すことによって、デストラクタが呼び出されませんTObject

次のように修正します。

destructor Destroy(); override;

この場合は問題ではありませんが、継承されたコンストラクターとデストラクターをコンストラクターとデストラクターで呼び出す習慣を身に付ける必要があります。そうすれば、コンストラクターとデストラクターで行う以上のことを行うクラスから派生するときにTObject、スーパークラス コードが確実に実行されます。

constructor tLeakClass.Create (AOwner : TComponent);
begin
  inherited Create;
  fsPrinter := TECR_Text.Create(AOwner);
end;

destructor tLeakClass.Destroy();
begin
  fsPrinter.Free;
  inherited;
end;

ただし、FastMM レポートは少し奇妙です。TECR_Textオブジェクトが漏洩したことを報告します。ただし、フォームが所有するものとして作成したため、フォームはそれを削除する必要があります。問題のコードで明らかに漏れているオブジェクトは、のインスタンスです。tLeakClass

したがって、クラスには見えない他の問題があるのではないかと思います。おそらく、あなたは同じエラーを犯し、override私たちが見ることができないクラスのデストラクタを省略しました.

于 2013-03-31T15:40:32.617 に答える