I started this post as “A case against FreeAndNil” but soon found out about [WayBack/Archive.is] A case against FreeAndNil – Community Blogs – Embarcadero Community.
Recently I was refactoring a bunch of code that was classed based to become interface based.
The old code had a lot of references to classes like this:
FMyField: TMyClass;
The compiler had detected those as compiler errors so now they were like this:
FMyField: IMyInterface;
But the compiler would still happily compile code (for instance in destructors) containing:
FreeAndNil(FMyField);
The only way that FreeAndNil
can be implemented is with an untyped var
parameter:
procedure FreeAndNil(var Obj); var Temp: TObject; begin Temp := TObject(Obj); Pointer(Obj) := nil; Temp.Free; end;
This var
construct makes it typeless: the method dutifully accepts anything even something that isn’t a TObject. And there is hardly anyw any (cheap) way to detect it’s actually a TObject (as it likekly won’t have RTTI).
What happens when you call it with an interface as parameter is that the hard cast will execute a “Free” method that might not be a method at all. Or is a method that does something totally different, expects more parameters (hello stack-underflow!) or has other harmfull side effects.
So contrary to the past – where most people would prefer FreeAndNil – I’m back to the below code in class based situations:
FMyField.Free(); FMyField := nil;
This looks like a strange but it has the visual clue that both are being executed and belong together.
Edit: the above is why I wrote a generic
FreeAndNil
inside a helper that limits itself toTObject
references. The gist is below. This is the declaration:
class procedure FreeAndNil<T: class>(var Value: T); static;
Some future enhancements:
- The
nil
could be a totally different value likePointer(-1)
abstracted away into a const likeUnusedPointer
to better detect use-after free. A similar construct (with the drawback of using an untyped var parameter) is suggested at [WayBack] Don’t abuse FreeAndNil anymore – DelphiTools. - Some hinting comments to a code formatter will not break the lines apart. I need to look into [WayBack] How to turn off source formatter in Delphi 2010 for sections of code? – Stack Overflow more closely later.
Blast from the past which is how I used to do it:
- [WayBack] Why should you always use FreeAndNil instead of Free
- [WayBack] delphi – Which is preferable: Free or FreeAndNil? – Stack Overflow
–jeroen