Delphi:内存泄漏警告消息

Delphi: Memory Leak Warning Message

我正在 Delphi 2006 年创建一个小型应用程序。在其中一个 class 中有另一个 class 的 属性。在我的 onCreate 事件中,我实例化了对象并在 onDestroy 事件中销毁了它们。当我关闭应用程序时,我收到内存泄漏警告。老实说,我无法识别内存泄漏。这是我正在使用的代码,非常感谢您的帮助。

我无法 post 错误消息的图像,但这里有描述。

An unexpected memory leak has occurred. The unexpected small block leaks are:
21 - 28 bytes: TPermanentAddress x 1

这里是 class:

unit uUser;

interface

uses
  classes,SysUtils,Dialogs;


type
TAddress = class
private
 FStreetAddress : string;
 FCity          : string ;
 FState         : string;
 FZipCode       : string;

 procedure setStreetAddress(const Value : string);
 procedure setCity(const Value : string);
 procedure setState(const Value : string);
 procedure setZipCode(const Value : string);

 protected

 public
 property StreetAddress : string read FStreetAddress write setStreetAddress;
 property City : string read FCity write setCity;
 property State : string read FState write setState;
 property ZipCode : string read FZipCode write setZipCode;


end;

type
  TPermanentAdddress = class (TAddress)
  private
  FStartDate     : string;
  FEndDate       : string;

  procedure setStartDate(const Value : string);
  procedure setEndDate(const Value : string);

  protected

  public

  property StartDate : string read FStartDate write setStartDate;
  property EndDate   : string read FEndDate write setEndDate ;
  end;


type
TUser = class(TObject)
  private
  FFirstName : string;
  FAddress : TPermanentAdddress;
  procedure setFirstName(const Value : string);
  procedure setAddress(const Value : TPermanentAdddress);

  protected

  public
  constructor Create(); reintroduce; overload;
  destructor Destroy();  override;
   property FirstName : string read FFirstName write setFirstName;
   property Address : TPermanentAdddress read FAddress write setAddress;

end;

implementation

procedure TAddress.setStreetAddress(const Value : string);
begin
  FStreetAddress := value;
end;

 procedure TAddress.setCity(const Value : string);
 begin
   FCity := Value;
 end;
 procedure TAddress.setState(const Value : string);
 begin
   FState := Value;
 end;
 procedure TAddress.setZipCode(const Value : string);
 begin
   FZipCode := Value;
 end;

 //Permanent Address
  procedure TPermanentAdddress.setStartDate(const Value : string);
  begin
    FStartDate := value;
  end;
  procedure TPermanentAdddress.setEndDate(const Value : string);
  begin
    FEndDate := Value;
  end;

  //tvxpatient
  procedure TUser.setFirstName(const Value : string);
  begin
    FFirstName := Value;
  end;
  procedure TUser.setAddress(const Value : TPermanentAdddress);
  begin
    FAddress := Value;
  end;

  constructor TUser.Create();
  begin
   FAddress := TPermanentAdddress.Create;
  end;

  destructor TUser.Destroy();
  begin
  //FAddress.Free;
  end;

end.

这是表格:

unit Home;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, uUser, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
protected

  public
    { Public declarations }
  aUser : TUser;

  end;
var
  Form1: TForm1;

implementation
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
addr : TPermanentAdddress;
begin
  aUser := TUser.Create;
  aUser.Address := TPermanentAdddress.Create;
  aUser.FirstName := 'test';
  aUser.Address.StartDate := '03/10/2015';
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 aUser.Address.Free; // I am destroying it here, so I thought.
 aUser.Free;
end;

end. 

在项目中,我开启了ReportMemoryLeaksOnShutdown。

program Testing;

uses
  Forms,
  Home in 'Home.pas' {Form1},
  uUser in 'uUser.pas';

{$R *.res}

begin
  ReportMemoryLeaksOnShutdown := DebugHook <> 0;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
destructor TUser.Destroy();
begin
  //FAddress.Free;
end;

这里你破坏失败FAddress。因此内存泄漏。

您还应该调用继承的析构函数。它应该是这样的:

destructor TUser.Destroy;
begin
  FAddress.Free;
  inherited;
end;

最重要的是,你创建了两次 Address 是错误的。而不是:

procedure TForm1.FormCreate(Sender: TObject);
var
  addr : TPermanentAdddress;
begin
  aUser := TUser.Create;
  aUser.Address := TPermanentAdddress.Create;
  aUser.FirstName := 'test';
  aUser.Address.StartDate := '03/10/2015';
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 aUser.Address.Free; // I am destroying it here, so I thought.
 aUser.Free;
end;

你需要:

procedure TForm1.FormCreate(Sender: TObject);
begin
  aUser := TUser.Create;
  aUser.FirstName := 'test';
  aUser.Address.StartDate := '03/10/2015';
end;

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

就个人而言,我会使用 TForm1 的 constructor/destructor 而不是 OnCreateOnDestroy 来管理拥有的对象。