views:

375

answers:

5

Hi all,

What is the basic difference between Free and FreeAndNil?

Is FreeAndNil = Free + Nil?

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

I am not getting these when goggling can someone help me.

Thanks in advance.

+12  A: 

See

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.)

Andreas Rejbrand
"some would argue that in many cases (but not all), trying to use an object that has been freed is a bug by itself" - that's always an bug, not "sometimes". Variables and Objects are different beasts: variables might at times be assigned "nil", but that's not an nil object, is just an unassigned variable.
Cosmin Prund
@Cosmin Prund: Of course. I will change this.
Andreas Rejbrand
@Cosmin - not quite true. Variables that are unassigned are highly unlikely to be NIL unless they are strings or interface references. Unassigned class members on the other hand are certain to be NIL unless you deliberately override the NewInstance implementation.
Deltics
+2  A: 

@Bharat, the difference between Free and FreeAndNil is that in addition to free memory used by an object FreeAndNil sets the object reference to nil.

you can check theses links for discussions about use Free or FreeAndNil

RRUZ
+6  A: 

Basically, FreeAndNil frees the object and then sets the reference to nil. 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.

Mason Wheeler
Actually, it puts the reference in a local var, nils the reference and then frees the object using the local var. FreeAndNil should have been named NilAndFree... :)
Marjan Venema
Yep. Incomplete destructors and FreeAndNIL() are not good bedfellows.
Deltics
@Marjan, I recently had a case where that naming would have probably saved me some time in identifying a bug in an overly complex singleton implementation that involved accessing class variables from a destructor which had previously been `FreeAndNil`'d... ;)
Oliver Giesen
A: 

Short answer: use FreeAndNil, why not?

Long answer: see other replies and links.

Alexander
+2  A: 

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

Jeroen Pluimers