Delphi: сообщение об утечке памяти

Я нахожусь в процессе создания небольшого приложения в Delphi 2006. В одном из классов есть свойство другого класса. В моем событии onCreate я создал объекты и уничтожил их в событии onDestroy. Когда я закрываю приложение, я получаю предупреждение об утечке памяти. Я, честно говоря, не могу идентифицировать утечку памяти. Вот код, который я использую, ваша помощь будет принята с благодарностью.

Я не могу опубликовать изображение сообщения об ошибке, но вот описание.

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

Вот класс:

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.

1 ответ

Решение
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 скорее, чем OnCreate а также OnDestroy на управляемые объекты.

Другие вопросы по тегам