代码之家  ›  专栏  ›  技术社区  ›  aleroot

FastMM报告在FormDestroy上释放的类内存泄漏

  •  3
  • aleroot  · 技术社区  · 13 年前

    我在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
    

    Here 你可以下载完整的 SSCCE 表示问题的项目示例(要运行示例,请单击按钮并关闭表单)。

    为什么 fs打印机 物体泄漏?如何避免泄漏?

    1 回复  |  直到 13 年前
        1
  •  6
  •   David Heffernan    13 年前

    您的析构函数声明不正确。您写道:

    destructor Destroy();
    

    但必须重写中声明的虚拟析构函数 TObject 。如果你不这样做,那么你的析构函数将不会被调用 Free 它调用中声明的虚拟析构函数 T对象 .

    这样修复:

    destructor Destroy(); override;
    

    尽管在这种情况下这并不重要,但您应该养成在构造函数和析构函数中调用继承的构造函数和析构函数的习惯。这样,当你从一个做得比 T对象 在它的构造函数和析构函数中,您将确保超类代码运行。

    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 在我们看不到的类的析构函数上。