Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is preferable: Free or FreeAndNil?

Tags:

delphi

What is the basic difference between Free and FreeAndNil?

Is FreeAndNil = Free + Nil?

When should I use Free and when should I use FreeAndNil?

like image 362
Bharat Avatar asked Jul 01 '10 15:07

Bharat


3 Answers

See

  • delphibasics-FreeAndNil
  • docwiki.embarcadero-FreeAndNil
  • pages-freeandnil [Broken]
  • eurekalog-freeandnil
  • blogs.embarcadero (via Wayback Machine)
  • ...

And have a look at the implementation:

procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;

Examples

Consider the following code:

procedure TForm1.FormCreate(Sender: TObject);
var
  bm: TBitmap;
begin
  bm := TBitmap.Create;
  bm.LoadFromFile('C:\Users\Andreas Rejbrand\Documents\RAD Studio\6.0\Demos\DelphiWin32\VCLWin32\Football\up.bmp');
  bm.Free;

  if Assigned(bm) then
    bm.SaveToFile('C:\Users\Andreas Rejbrand\Desktop\test.bmp')
  else
    ShowMessage('Cannot save! The bitmap does no longer exist!');
end;

This will create an error or an invalid (empty) bitmap on my desktop, because I try to use an object that has been freed. Yes, even though bm has been freed, it is still "assigned", i.e. bm still points to a memory adress, even though there is nothing (usable) there. To overcome this, one can set bm := nil, as a safeguard, Then assigned(bm) will return false, as one would want. More or less, FreeAndNil(bm) is a shorthand for bm.Free; bm := nil. The first statement frees all memory (and OS resources, CPU time etc. used by the object), and bm := nil sets the "pointer" bm to nil, so that bm no longer points to the place where the object used to be, but no longer is. This way you (and routines like assigned) will not get fooled to believe that there still is a bitmap object.

Discussion

Some say that you should always use FreeAndNil(foo) rather than foo.Free. Well, why not? The additional instruction foo := nil will probably not take too many nanoseconds to execute, and indeed assigned(foo) = false is a very nice property of a freed object. But then again, if you know what you are doing, and know that you will never use the foo object again after freeing it, then you could stick to just foo.free. Really, some would argue that in many cases (but not all), trying to use a variable of a freed object is a bug by itself. (Of course there are cases where you do this intentionally - you have an object foo that sometimes is assigned and sometimes is not.)

like image 106
Andreas Rejbrand Avatar answered Oct 16 '22 08:10

Andreas Rejbrand


Basically, FreeAndNil sets the reference to nil and then frees the object. This marks it as unassigned. So the only reason you would need to use FreeAndNil is if your code is going to reuse the reference. If you're in a destructor or a finally block, freeing objects that you're never going to touch again, just use Free.

See Delphi Memory Management Made Simple for an example of when I did find it useful. Mghie's comment at the bottom is also worth reading.

like image 27
Mason Wheeler Avatar answered Oct 16 '22 09:10

Mason Wheeler


I'll answer in a different way.

Maybe, filling your object reference with nil after freeing your object is not always a good idea.

That way, you do not have a distinction between a reference that was never used (and hence is nil), and a reference that has been used, but should not be used in the future.

So, filling it with a magic number (similar to what the FastMM memory manager can do with the content of blocks of memory when those blocks are freed).

--jeroen

like image 10
Jeroen Wiert Pluimers Avatar answered Oct 16 '22 09:10

Jeroen Wiert Pluimers