views:

252

answers:

4

I haven't been able to find the answers to a couple of my Delphi memory management questions. I could test different scenarios (which I did to find out what breaks the FreeAndNil method), but its takes too long and its hard! But seriously, I would also like to know how you all (Delphi developers) handle these memory management issues.

My Questions (Feel free to pose your own I'm sure the answers to them will help me too):

  1. Does FreeAndNil work for COM objects? My thoughts are I don't need it, but if all I need to do is set it to nil than why not stay consistent in my finally block and use FreeAndNil for everything?

  2. Whats the proper way to clean up static arrays (myArr : Array[0..5] of TObject). I can't FreeAndNil it, so is it good enough to just set it to nil (do I need to do that after I've FreeAnNil'd each object?)?

Thanks Guys!

+1  A: 

Regarding static arrays, if you created the contents of the array, just free those objects you created. You don't need to do anything special to clean up the space used by myArr itself.

Frank Shearar
+1  A: 

COM objects are automatically reference counted; as soon as variable goes out of scope or the object that has the interface pointer as a field is deleted Delphi will call _Release and the object will delete itself. You don't need to set anything to nil explicitly.

For static arrays you need to loop over them and free each object explicitly.

Craig Peterson
+6  A: 

COM objects are referenced via Interfaces, which you don't need to do anything to free. The compiler takes care of the necessary reference-counting logic to make sure the COM object will be disposed of at the right time.

As for static arrays, (or dynamic arrays, for that matter,) they don't need to be freed by you either. If they contain objects then the objects have to be freed at the appropriate time, but the arrays don't.

Also, never use FreeAndNil on anything that's not an object reference. Using it with interfaces or other variables can corrupt memory. It's best to never use it (use Free instead) unless you're dealing with an object that you need to free and then reuse later.

Mason Wheeler
Somebody should write a great article named "FreeAndNil considered harmful" :)
Serg
Well, I haven't seen that particular title, I don't think, but see http://blogs.embarcadero.com/abauer/2010/02/05/38910 and http://blogs.embarcadero.com/abauer/2010/02/16/38916 from Allen Bauer.
Mason Wheeler
Thanks, I'm running into some of this free and nil nonsense now ...I've read 2-3 articles that suggest using FreeAndNil as much as possible :(
nomad311
Yeah, some people like it a lot, but IME it's actually better to use it as *little* as possible.
Mason Wheeler
+1 mainly for the advice to use FreeAndNil as little as possible
Gerry
A statement like "It's best to never use it" needs to come with a reason. It's a very controversial statement, see the comments to the Bauer blog posts for proof. The questioner seems to have problems with basic memory management issues in Delphi, giving him one more rule to blindly follow without understanding the rationale behind it won't help.
mghie
@Mghie: Gimme an hour or two...
Mason Wheeler
@Mghie: OK, it took a bit longer than that, but here's a blog post that explains the principles and also gives some reasoning behind how to use FreeAndNil: http://tech.turbu-rpg.com/106/delphi-memory-management-made-simple
Mason Wheeler
+2  A: 

First, in most situation, FreeAndNil is a bit of overkill. It's handy when you free and object's field outside it's destructor, or on a global(ugly) variable. But most of the time, just calling free is enough.

As you should know, an object variable is actually a pointer to the object's data. When you call Free, that buffer is freed (after the destructor is ran, of course), but the Object variable still points to the memory position that was just freed. It's called a "Dangling pointer". Having a dangling pointer is not a problem as long as you KNOW it's dangling in that context. For exemple:

Procedure Myproc;
var vString : TStringList;
begin
  //Here, vString is "dangling"
  vString := TStringList.Create;
  //Here, vString is valid
  try
    //Do some stuff
  finally
    vString.Free;
  end;
  //Here, vString is "dangling"...  But who care, it's about to go out of scope and we won't use it again.
end;

Calling FreeAndNil makes more sense on global variable where you don't know exactly when or how the variable can be freed. With that being said, there is nothing wrong in calling FreeAndNil all the time (except in very tight loops where you try to get every oz of performance).

Now, for the COM objects... Like Mason stated, they are reference counted. So if you hold the only reference to that interface, calling MyInterface := nil; will free it. But when/if the variable goes out of scope, the compiler take care of adding cleanup code to make sure the interface reference is decremented. So if you are trying to keep the memory requirement to a minimum, set the interface to nil. Otherwise, it doesn't matter that much.

As for your array... You can just call Free on every items in the list... Optionnaly set them to nil after.

Ken Bourassa