52

What is the basic difference between Free and FreeAndNil?

Is FreeAndNil = Free + Nil?

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

Usama Abdulrehman
  • 1,041
  • 3
  • 11
  • 21
Bharat
  • 6,828
  • 5
  • 35
  • 56
  • @Sertac the thread, like many others, disappeared – mjn Jan 12 '12 at 07:25
  • 1
    New discussions are on non-tech [here](https://forums.embarcadero.com/thread.jspa?threadID=65321&tstart=15) and [here](https://forums.embarcadero.com/thread.jspa?threadID=63906&tstart=0) – mjn Jan 12 '12 at 07:29
  • @mjn: Many older threads disappered after the server crash a few weeks ago. You already pointed to the newer threads on the subject. – Rudy Velthuis Jan 24 '12 at 19:53
  • 4
    How did I never see this question? :-) – Nick Hodges Nov 21 '13 at 21:19
  • Wow. 48 votes and 11 bookmarks. So much mythology around this little function. Maybe a proper Delphi help page/documentation will clear up some of the fog. – Gabriel Oct 30 '20 at 13:54
  • https://blogs.embarcadero.com/freeandnil-delphi-developer-debate/ – Gabriel Jul 01 '22 at 15:51

5 Answers5

51

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

Jim McKeeth
  • 38,225
  • 23
  • 120
  • 194
Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • 5
    "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 Jul 01 '10 at 19:48
  • 1
    @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 Jul 01 '10 at 21:10
  • 6
    I would go so far as to say that a programmer should make his intentions clear by using foo.Free when foo is not referenced again, and FreeAndNil(foo) when it is. Don't use FreeAndNil(foo) when foo.Free would do, because it suggests to the reader that foo _needs_ to be set to nil. – Ian Goldby May 11 '12 at 07:31
  • 1
    Of course it is wrong to use an object that has been freed. There's no doubt about that. But the real point is what happens when you actually do it (and in the Real World™ people make mistakes): If it is a NIL pointer, the behaviour is a) very predictable (you get an NPE) and b) mostly easy to spot. A write access via invalid pointer that is non-nil may a) corrupt your system (= security issue) and b) can be extremely difficult to find. If one's #1 priority is to "be right" ... your wish is granted, but I recommend to prepare. You will need to pay the toll that comes along with it. – JensG Jan 17 '17 at 16:11
  • Sorry folks (esp. @Ian) - discussing whether to set `foo`to `nil` after `foo.Free` is IMHO hairsplitting, nitpicking, and very close to ridiculous. I can't imagine a situation where not cleaning up properly makes a huge lot of sense, nor at least some sense. For whom this is a point worth noting or even discussing, please be consequent, abandon Delphi or whatever other high level language and stick to assembler. – Semanino Sep 27 '17 at 11:29
  • @Semanino - ok, ok, we get it. you never made a mistake. your code is 100.0% free of errors. Your clean up is impeccable. you are God-like. even God is flawed (it took him 6 days to make the earth and humans and he DID a lot of mistakes in the process). – Gabriel Nov 23 '18 at 10:53
  • @Rigel you maybe got me wrong - I ment that setting `foo`to `nil` after `foo.Free` should be no question at all and one should **always** do that. `FreeAnNil(foo)` is the perfect and easy way for it. And - of course I AM impeccable! ;-) Because I always use `FreeAndNil()` – Semanino Mar 20 '19 at 14:15
  • @Semanino - "Because I always use FreeAndNil" - then I like you :) – Gabriel Mar 20 '19 at 14:48
  • the second and the fifth link don't work properly any more – Fabrizio Jun 19 '20 at 07:38
21

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.

Kromster
  • 7,181
  • 7
  • 63
  • 111
Mason Wheeler
  • 82,511
  • 50
  • 270
  • 477
  • 4
    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 Jul 01 '10 at 19:23
  • Yep. Incomplete destructors and FreeAndNIL() are not good bedfellows. – Deltics Jul 01 '10 at 21:10
  • 1
    @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 Jul 01 '10 at 22:06
  • @mason - The reason not to use FreeAndNil is because "it’s not typesafe" ? Come on. There are quite a few things are not type safe in Delphi. Should we stop using them all together? By the way, safety of FreeAndNil was dramatically improved in Sydney (or Rio? don't remember) – Gabriel Apr 22 '21 at 10:02
10

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 Wiert Pluimers
  • 23,965
  • 9
  • 74
  • 154
  • I am strongly pro FreeAndNil but your "magic number" idea is also appealing. – Gabriel Mar 20 '19 at 14:50
  • This statement makes sense only if your program logic EXPLICITLY rely on those "create object once, dispose and never re-create" logic. Which is.... unusual.... Can you give an example where you actually used this technique? – Gabriel Oct 30 '20 at 13:29
  • @Z80 for instance when zapping authentication and authorisation information, and with singletons (which revealed use after free). – Jeroen Wiert Pluimers Apr 20 '21 at 09:38
  • Can you please show a small compilable project where you MUST use an object after free? – Gabriel Apr 21 '21 at 14:07
  • @Z80 the point is that a project should not, but some do and are in error. One day when I have fully recovered (see profile), I plan to write a FastMM conference session in how to detect these situations. Code then should end up in https://github.com/jpluimers/Conferences – Jeroen Wiert Pluimers Apr 21 '21 at 17:18
  • "the point is that a project should not, but some do and are in error" - Sorry. I still don't understand you. So you recommend to other people NOT to use FreeAndNil because some projects MIGHT be poorly written and FreeAndNil will cause the project to crash? In this case the problem is not with FreeAndNil. It is with the project. – Gabriel Apr 22 '21 at 09:55
  • @Z80 my argument is basically like the SQL null discussion: what does it mean and at what point in time. One writeup of that is here: https://datatechnologytoday.wordpress.com/2017/07/18/what-the-null-handling-missing-information-in-database-systems/ Distinguishing these can aid troubleshooting or even prevent errors. In a sense it is a step-up to https://en.wikipedia.org/wiki/Fuzzing – Jeroen Wiert Pluimers Apr 22 '21 at 12:03
  • Please let us know when you have a piece of code where replacing Free with FreeAndNil will actually crash the program. – Gabriel Apr 22 '21 at 12:49
  • @Z80 I will. In the mean time, here is one reason not to use the current version of `FreeAndNil`: https://wiert.me/2017/12/21/another-case-against-freeandnil/ – Jeroen Wiert Pluimers Apr 22 '21 at 17:03
7

@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
  • 134,889
  • 20
  • 356
  • 483
  • I really like you and your work on SO but this time I don't like your answer. It seems to promote the "don't use FreeAndNill" camp. Yet, as usual no evidence is provided: three of your links are down! The only one still working points to an article that is actually pro FreeAndNil (true, not directly; it proposes to use FreeAndInvalidate instead of FreeAndNil)! – Gabriel Apr 21 '21 at 14:09
3

Even if doesn't seem to be much different than Free, FreeAndNil will help you a lot while hunting bugs in your code.

How it saves your ass (access after free)
Just think what happens if you DON'T use FreeAndNil and then somewhere in your code you access a freed object. If you are terrible lucky, your program will immediately crash when it runs home (yes that crash is a 'good' crash). If you are a bit unlucky it will crash in customer's computer.

But this is not all. If your re unlucky, the program will not crash immediately. Or it will never crash, instead it will read or ven worst write) random chunks of memory. This is where the real pain starts!

Will it harm your program?
As others already pointed, the FreeAndNil itself is not bad. The FreeAndNil function is not broken/obsolete or something like this and it will not corrupt your code. It is a legitimate RTL function that frees and object and then puts its pointer to NIL.

Facts vs opinions
Some will argue that relying on FreeAndNil may lead or indicate a design flaw, but they cannot justify this in any way. It is just their personal option. On the other hand, a program that cranshes randomly and undebuggingly (he he... I just create a new word) because you refused to use FreeAndNil is a fact not an opinion.

Come on... even on local variables?
I use FreeAndNil EVEN on a local variable. Using it on a local variable seems POINTLESS since the variable vanishes as soon as you exit the procedure.
Think that you may at a later date add more code at the end of the procedure, AFTER the point where you freed the object; code that will (accidentally) try to access the freed object. If the object was NIL, BABUM, instant AV (example).

A resource hog?
Some super-conservative programmers may say this simple call will waste RAM and CPU resources. I like to deliver small/fast/monolithic applications too!
But I don't think that removing using FreeAndNil will waste more than few bytes of RAM and CPU cycles. It will not make a real difference in the day-by-day life.

When you think that a single graphic resource like a TButton glyph or your program's icon can take 50-300KB (and your program can have dozens of these) it is pointless to argue about the resources "wasted' by FreeAndNil.

Gods vs programmers
Some people may say they never ever accessed a free object (basically meaning they never make mistakes) so they don't need FreeAndNil in this case. Well, I am not a robot. I do mistakes. I am not afraid to recognize it.

Pros
Mason Wheeler already points to a article that shows the 'lazy creation' method that uses FreeAndNil that we all used one day: http://tech.turbu-rpg.com/106/delphi-memory-management-made-simple

Cons
No actual/solid evidence.

Allen Bauer has an article named A CASE when FreeAndNil is your enemy suggesting that using the FreeAndNil in a very particular and special case (the destructor of a visual component) could be bad. There is no code attached to the article that we can compile, only some possible scenarios where FreeAndNil might cause problems.

Allen states that FreeAndNil should be replaced with better methods. For example with FastMM.
However, this discussion demonstrates (with compilable code) that FastMM fails while FreeAndNil saves the day.


Where is the proof?
At this point I would love to have even ONE SINGLE tiny piece of concrete/compilable code to show that FreeAndNil could do harm.
On the other hand, we do have plenty (see links) of examples that shows how FreeAndNil can save our ass.

For those that are against FreeAndNil please enlighten us, by posting some compilable code.

Gabriel
  • 20,797
  • 27
  • 159
  • 293
  • 3
    -1. "Always" is wrong. If you have a local variable in a method, there is little or no need to use FreeAndNil, because the var is only accessible from within the local scope. If you can't **see** that you don't need FreeAndNil there, you need to refactor your code to reduce the number of lines in that method. It's a poor idea to ever give an answer that says "always" unless you can absolutely prove that there are no exceptions to that rule. – Ken White Apr 04 '14 at 12:50
  • No, you never "accidentally" upgrade a local to a global. Use of global variables should be a rare thing that is carefully considered. Using FreeAndNil to cover possible careless programming is simply another form of careless programming. Any function call has some overhead (even if it is negligible), and while the impact might be small it's still unnecessary CPU cycles, memory allocation, etc. So my vote still stands. – Ken White Apr 04 '14 at 14:41
  • If you can't say you *never accidentally upgrade a local to a global*, and your full-time job is writing code, you should step carefully back from the keyboard and find a new job. I can honestly say that in the last decade I have *never* accidentally upgraded a local variable to a global one and had an issue in a method that uses that local variable where the proper solution would be FreeAndNil. I have several production applications totaling well over 5 million lines of code, and a grep of the source finds two instances of FreeAndNil in my own code. – Ken White Apr 04 '14 at 14:50
  • 4
    Ken, we got your point :) You donwvoted my post. I totally accept that. I don't protest. It is anybody's right to defend their personal opinion. Some people agree suing FreeAndNil some don't. Not necessary being so hateful. – Gabriel Apr 06 '14 at 09:58
  • As usual, every few years (or every time Delphi is sold to a new owner?) content of the site is purged (or moved around) so the links are not working anymore. So, the link to Allen Bauer's article is not valid anymore. – Gabriel May 10 '17 at 07:32
  • Allen Bauers blogs restored at his own blog site. You can find the article about FreeAndNil [here](https://blog.therealoracleatdelphi.com/2010/02/a-case-when-freeandnil-is-your-enemy_16.html) – LU RD Oct 30 '20 at 13:23
  • That's nice! There is good information on that website. And now that we can access it again, let's quote it "I was specifically referring to using FreeAndNil in the DESTRUCTOR" :) – Gabriel Oct 30 '20 at 13:38
  • I Delphi 10.4, the `FreeAndNil()` procedure is somewhat changed. The reason for this change is to only allow objects to be passed. In previous versions, you could pass interfaces and anything else. Doing so will harm the integrity of the program. The fix is doing that in a conspicuous way, breaking the contract of parameter passing. See [Delphi FreeAndNil: Looking for an alternate implementation](https://stackoverflow.com/q/62479148/576719) – LU RD Nov 04 '20 at 14:02
  • @LURD - I know. I think Emba has also an official article about this. This change makes FreeAndNil even better. – Gabriel Nov 05 '20 at 15:10