简体   繁体   中英

Delphi: Memory Leak Warning Message

I am in the process of creating a small application in Delphi 2006. In one of the classes there is a property of another class. In my onCreate event, I instantiated the objects and also destroy them in the onDestroy event. When I close the application, I get a memory leak warning. I honestly cannot identity the memory leak. Here is the code that I am using, your help will be greatly appreciated.

I can't post an image of the error message, but here is a description.

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

Here is the 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.

Here is the Form:

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. 

In the project, I turned on 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;

Here you fail to destroy FAddress . Hence the memory leak.

Your should also call the inherited destructor. It should look like this:

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

On top of this, you are wrong to create Address twice. Instead of:

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;

You need:

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;

Personally I would use the constructor/destructor of TForm1 rather than OnCreate and OnDestroy to managed owned objects.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM