Free and Nil..... or Nil and Free.....

Hi,

I have a basic Delphi question.

I've seen code where people use

FreeAndNil(MyObject);

Open in new window

Some times other people write
MyObject.Free();
MyObject := nil;

Open in new window



However the FreeAndNil function code is this:

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

Open in new window



Which seems to first nil the object, then free it.
As opposite as what I've seen in other's people code where in separate lines they write Free first, then set it to Nil

Are both ways okey?
If not, why?
Please elaborate :)

LVL 1
fischermxAsked:
Who is Participating?
 
Ephraim WangoyaCommented:

Both are ok
Lets look more closely

1.
    MyObject.Free();
    MyObject := nil;
Here MyObject is apointer to a memory location
MyObject.Free frees the memory pointed to by MyObject
However, MyObject is still pointing to a memory location which now does not exist. If you did Assigned(MyObject)it may still return true but using it you will get access violation since the memory pointed to is now invalid
MyObject := nil This sets it to point to nowhere so checking for valid pointer returns false

2.
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;

 Pointer(Obj) := nil; - You set the pointer to point to nothing but the object still exists in memory
                                 Assigned(Temp) will return true
 Temp.Free - You actually free the Object from memory  

Either method ends with same result
So its much better to use FreeAndnil() and let it do everything for you
0
 
jimyXCommented:
I quote from the Delphi in a Nutshell about Objects:
http://oreilly.com/catalog/delphi/chapter/ch02.html

To get rid of the object when your program no longer needs it, call the Free method. To ensure that the object is properly freed, even if an exception is raised, use a try-finally exception handler. (See Chapter 1, Delphi Pascal, for more information about try-finally.) For example:

Obj := TSomeOtherClass.Create;
try
  Obj.DoSomethingThatMightRaiseAnException;
  Obj.DoSomethingElse;
finally
  Obj.Free;
end;

When freeing a global variable or field, always set the variable to nil when freeing the object so you are not left with a variable that contains an invalid pointer. You should take care to set the variable to nil before freeing the object. If the destructor, or a method called from the destructor, refers to that variable, you usually want the variable to be nil to avoid any potential problems. An easy way to do this is to call the FreeAndNil procedure (from the SysUtils unit):

GlobalVar := TFruitWigglies.Create;
try
  GlobalVar.EatEmUp;
finally
  FreeAndNil(GlobalVar);
end;
0
 
Geert GOracle dbaCommented:
FreeAndNil was introduced in D5 to make life a little easier for the developer

Setting a reference to a object = nil also clears the reference count
allowing it to free the object > used with com objects
0
Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

 
jimyXCommented:
>   "I've seen in other's people code where in separate lines they write Free first, then set it to Nil"
>   "Are both ways okey?"
>   "If not, why?"

When dealing with variables, you should call Free first and then Nil.
Actually there is a difference, to show you what happens when you use free before nil or nil before free, try this code:
Nil before Free:
procedure TForm1.Button1Click(Sender: TObject);
var
  Btn:Tbutton;
begin
  Btn:=Tbutton.Create(Form1);
  Btn.Parent:= Form1;
  Btn:= nil;
  Btn.Free;
end;

Open in new window

The Button still on the form.

Free before Nil:
procedure TForm1.Button1Click(Sender: TObject);
var
  Btn:Tbutton;
begin
  Btn:=Tbutton.Create(Form1);
  Btn.Parent:= Form1;
  Btn.Free;
  Btn:= nil;
end;

Open in new window

The button is freed.

To call nil before free you must assign a pointer:
procedure TForm1.Button1Click(Sender: TObject);
var
  Btn:Tbutton;
  T:Pointer;
begin
  Btn:=Tbutton.Create(Form1);
  T:= Btn ;
  Btn.Parent:= Form1;
  Btn:= nil;
  TObject(T).Free;
end;

Open in new window


So, as per Delphi in a Nutshell, when FreeAndNil() is called:
  Temp := TObject(Obj);
  Pointer(Obj) := nil;               // this is the variable which is set to nil
  Temp.Free;                           // now the Object is freed
0
 
ThommyCommented:
This is a good resource for learning about the difference between Free and FreeAndNil...


Which is preferable: Free or FreeAndNil?
http://stackoverflow.com/questions/3159376/which-is-preferable-free-or-freeandnil
0
 
MerijnBSr. Software EngineerCommented:
For what it's worth: I normally only use FreeAndNil if it has a documenting purpose. In other words, if the logic of the code will make use of the same object (or whatever) again. If this is not the case it has no purpose to use FreeAndNil() instead of Free().

So if I see a FreeAndNil() in my code, I know something special is going on and somewhere further down the logic a piece of code needs to know the state (freed or not) of an object for some reason.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.