Which is preferable: Free or FreeAndNil?
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
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.)
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.