Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi manage free memory

Tags:

delphi

SITUATION

I am studying Delphi from Marco Cantu's book and I already have experience with OOP because I usually work with Java and PHP. To better understand what I'm reading I've made this test:

type
 TFraction = class
  private
   number: double;
   num, den: integer;
   fraction: string;
   function hcf(x: integer; y: integer): integer;
  public
   constructor Create(numerator: integer; denominator: integer); overload;
   constructor Create(value: string); overload;
   function getFraction: string;
 end;

This is a super easy class that converts a decimal number into a fraction. I'm not including the other parts of the code where I define constructors and functions since they aren't useful for my question. I am creating the object in this way.

var a: TFraction;
begin

 a := TFraction.Create(225, 35);
 ShowMessage(a.getFraction);
 //The output of ^ is 45/7
 a.Free;

end;

QUESTION

From what I've learnt, I know that I have to get rid of the object once I've used it and in fact I am using the Free. In this way I free the memory and I avoid memory leaks.

By the way I see that I also have the possibility to override a destructor. I don't understand very well the behavior of the Free and the Destroy. I use the Free when I have to get rid of an object that I don't need anymore. When I override a destructor I can free the object and also make other actions?

In short, when is it good to use the Free? And when should I prefer the Destroy?

like image 315
Alberto Rossi Avatar asked Dec 24 '22 02:12

Alberto Rossi


1 Answers

In general, the destructor is used if you need to do something during object destruction which otherwise wouldn't be done automatically. Like freeing memory that you initialize in the constructor. In your example, there is no need to override the destructor, since (presumably) you don't create anything which needs to be destroyed manually.

Also, keep in mind that Destroy is not intended to be called by you at all - neither internally or externally. Free automatically takes care of calling that for you - with a little extra work going on. Free checks if the object is nil or not, and only calls Destroy if it's not nil.

Take this for example:

type
  TMyObject = class(TObject)
  private
    FSomeOtherObject: TSomeOtherObject;
  public
    constructor Create;
    destructor Destroy; override;
  end;

constructor TMyObject.Create;
begin
  inherited;
  FSomeOtherObject:= TSomeOtherObject.Create;
end;

destructor TMyObject.Destroy;
begin
  FSomeOtherObject.Free;
  inherited;
end;

Just as an added note, the usage I see above is missing something. What if the code between Create and Free raises some exception? The procedure would exit, and it would never be free'd. So instead, you should use a try / finally block...

a := TFraction.Create(225, 35);
try 
  ShowMessage(a.getFraction);
finally
  a.Free;
end;

This would ensure that no matter what happens between try and finally, the code between finally and end will always be called.

like image 94
Jerry Dodge Avatar answered Jan 14 '23 07:01

Jerry Dodge