Amazon.com Widgets Using FreeAndNil

Using FreeAndNil

By Nick at December 14, 2011 01:39
Filed Under: Delphi, Software Development

There has been a large and ongoing thread in the Delphi Non-Technical newsgroup about the proper use of FreeAndNil.  It’s been contentious and a tad touchy, too -- just as I like it.  Winking smile  The discussion falls out into two schools of thought:  Those that use FreeAndNil liberally and almost everywhere, and those that use it not at all or only in very rare, specific cases.  The former argues it is “defensive coding”, while the latter argues that it is the coding equivalent of spraying perfume on a skunk. 

I am in the latter camp.  I am in the the latter camp for a very good reason:  because the latter camp is right.  Winking smile There’s almost never a reason to use FreeAndNil in the new code that you write. 

And I want to be clear about that – I’m talking specifically about new code.   If you have old code that was designed in such a way that the scope of your pointers wasn’t tightly contained, than yes, you’ll probably have to use FreeAndNil to make that code work right.  But if you are doing that, I hope that you recognize that it is a problem and plan to refactor the code to contain the scope of your pointers.   I’m totally aware that legacy code may very well require that you nil pointers because the scope of those pointers is not well managed.  I know this because our system has such code, and thus contains calls to FreeAndNil

So, anyway, here’s an explanation why I think that FreeAndNil should only be used very, very sparingly. 

Before I start, I want to add that this blog post is heavily influenced by the eloquent wisdom and excellent explanations of a number of people who participated in the thread, including Bob Dawson, Wayne Niddery, Rudy Velthuis, Joanna Carter, Mark Edington, and Pieter Zijlstra.  Any profundity, excellent examples, pithy similes, or clear descriptions of things are very likely a result of me reading their posts in the thread.

Introduction

FreeAndNil is a function declared in the SysUtils unit and was introduced in Delphi 4, if I recall correctly.  I myself suspect that it was added more because of customer demand than because the R&D Team felt some need for it, and I’m reasonably sure that if they had it to do over again, they would not have added it at all.  But there it is.

The code for FreeAndNil is as follows:

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

That does seem a bit weird looking – you might expect it to look like this:

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

But it doesn’t.  It looks the way it does for a couple of reasons.  First, the parameter passed needs to be a var parameter because two things need to happen.  The object referenced needs to be freed, and the reference itself needs to be altered  -- that is, set to nil.  Thus, you need the freedom to change both the reference and the thing being referenced that the var parameter gives.  Second, the parameter is untyped because when you pass a var parameter, “Types of actual and formal var parameters must be identical.” Given that, if you declared the parameter as a TObject, then you could pass only a TObject to the method and not any of its descendants.

For instance, the following code will not compile:

program WontWork;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type

  TMyClass = class(TObject);

procedure Foo(var Obj: TObject);
begin
  WriteLn(Obj.ClassName);
end;

var
 MyClass : TMyClass;

begin
  MyClass := TMyClass.Create;
  try
    Foo(MyClass);
  finally
    MyClass.Free;
  end;
end.

I should point out that the use (or non-use) of FreeAndNil is not an insignificant and uncontroversial issue.  The thread that spawned this is typically long.  Allen Bauer, the Chief Scientist at Embarcadero, blogged about it, and quite a discussion ensued in the comments – so much so that he felt the need to blog about it again.  StackOverflow has a whole bunch of questions on the subject.  The VCL uses FreeAndNil in places that I wouldn’t necessarily approve of.   I think that in most places its use indicates, uhm, an “older” design choice that probably wouldn’t be made today, given newer language features.  In any event, clearly folks have strong views on this and that the use (or note) of FreeAndNil is not “settled science” (though I believe it should be…). 

Okay, So When Should You Use FreeAndNil?

In my mind, the answer to the question “When should I use FreeAndNil?” is “never”, or at least “Almost never, and if you must use it, make sure that there is a really, really good reason to do so and that you clearly document that reason”.  I myself have never (to my best recollection – I fully expect someone to find some obscure reference to code I wrote years ago that uses it….) used the procedure and see no possible scenario where I would want or need to in the code I write.  My recommendation is that you never use it either, because I don’t believe that you are writing code that needs it either (unless you are on the Delphi R&D team working in the bowels of the RTL, I suppose). 

Why I Don’t Use FreeAndNil and Why You Shouldn’t Either

There are a number of reasons why I don’t use FreeAndNil

First, a call to Free is sufficient. It gets the job done.  Free will, well, free the memory associated with your reference.  It does the job completely and totally.  Can’t do any more.  Setting a pointer to nil doesn’t get you anything.  The memory isn’t going to be more free or freed faster as a result of calling FreeAndNil.  Since it’s always a good practice to use exactly the right tool and nothing more, there’s no need to make the extra call.  Consider this – there’s no SetToZero call for integers, and if there were, why would you use it?  All code should be written with “considered intent,” and the indiscriminate use of FreeAndNil shows a lack of consideration and intent.

Second, using FreeAndNil where Free alone will do just fine obfuscates your code.  Using a call that executes unneeded instructions sends a message to future readers of the code that shouldn’t be sent.  A subsequent developer maintaining your code might look at the call and say “What the heck?  Why is FreeAndNil being used here and not just Free?  Is something going on here that I don’t know about?”  Time might then be wasted investigating, and a satisfactory answer may never be found.   Code that uses Free and FreeAndNil as exactly the same thing has reduced the amount of information that your code can convey.  And when you are dealing with something as important as memory management, you certainly don’t want to reduce the amount of information your code can convey.

FreeAndNil has a clear meaning – it is a very clear indicator that the pointer being freed has meaning outside of the scope where it is used.  If it doesn’t say that, then you shouldn’t use it.  If you use FreeAndNil when that is not the case, then you’ve sent a bad message to future maintainers.  Clarity in code is paramount – nothing should be done to decrease that clarity.  Code should be intentional and there for a reason.  Code that is there that doesn’t need to be can be misleading and distracting.  Misleading and distracting are not two thoughts that developers want crossing their minds while maintaining code. 

Free has meaning as well – it clearly states that the use of that pointer reference is now done and over with.  As noted above, there’s no need to call anything else.  The indiscriminate use of FreeAndNil fails to draw the clear distinction between Free and FreeAndNil.  Losing clarity in your code is bad, right?

Third, one of the justifications for using FreeAndNil is that it is defensive and that it protects against using a pointer at the wrong time.  The claim is that if a pointer is nil, and you then use that pointer, then you’ll know right away, and the bug would be easy to find. Thus, if you feel the need to use FreeAndNil to ensure that you don’t misuse a pointer somewhere, then it is very likely you have a design problem:  the scope of the pointer in question is larger than the use of that pointer in your code.  Or, in other words, the scope of a pointer and the scope of the use of that pointer aren’t the same and they should be.  If they aren’t , you are simply begging for trouble. 

If you want to really be persnickety, a variable that is broader in scope than it’s use is a form of a global variable.  And I would hope that we agree that global variables are bad.  If we can’t agree on that, well, then we can’t agree on anything.  Winking smile

Maintaining proper scope is critical to good, clean code.  I’ve discussed this before, and so I won’t go on about it here.  The germane point here is that if the scope of a pointer is of the “laying around waiting to be used”, then there is no limit to the mischief that this wayward pointer can cause.  So, if you don’t “leave a pointer lying around”, you can’t misuse it.  So, well, don’t leave a pointer lying around.   If you don’t leave roller skates at the bottom of the stairs, you can’t go careening down the hallway.   Keep your pointers and the use of those pointers in the same scope and you can’t misuse a pointer.  And you won’t feel the need to use FreeAndNil

And if you do use it for defensive reasons, you have to use it everywhere.  You have to use it in ever single place it is needed and you can’t miss a single place.  And, every single maintainer of the code after you has to as well.  One instance of not using it basically removes all the reasons for using it.  It’s a much better plan to simply control your scope and never feel the need for it. 

So, in the end…

In the end, I guess the argument for using FreeAndNil seems to boil down to:

“Of course I use FreeAndNil – it protects against bugs and makes other bugs easy to find, and besides, what’s the harm?”

Well, it would seem that none of those reasons is really true.  The real argument is:

“If your code requires you to use FreeAndNil to reveal and easily find bugs, then your design is wrong.  Good, clean code never feels the need to worry about errant pointers.”

Hey, look: design your code however you like. However, if you were to ask me, I’d say to design your code in such a way that FreeAndNil sends no signal, doesn’t find any bugs any sooner, doesn’t protect against anything, and thus becomes utterly superfluous.

Comments (56) -

12/14/2011 2:35:58 AM #

Jolyon Smith

Surely you must also admonish everyone to write code that never requires the use of "if Assigned(someReference) then" (other than on the result of some function or on a passed parameter) because code that never needs to use FreeAndNIL() should also never need to test whether the thing that never needs NIL'ing is in fact ever anything other than not NIL.

Jolyon Smith New Zealand |

12/14/2011 1:15:13 PM #

Nick Hodges

Jolyon --

Good point -- proper use of dependency injection should make such a construct pretty much unnecessary.

Nick Hodges United States |

12/14/2011 2:46:37 AM #

Alex

> First, a call to Free is sufficient.

A call to Destroy is sufficient too (in many cases). Free is overkill then. Why you don't use a Destroy? ;)

> Setting a pointer to nil doesn’t get you anything.

By not setting it to nil - you're lying to the compiler. You're telling that there is allocated memory at this location, and the truth is that it isn't. And lying to machine just isn't good.

> Consider this – there’s no SetToZero call for integers, and if there were, why would you use it?

Actually, it is. Well, sort of.

Consider TList.Clear (called withint destructor, BTW). Of course, it does many things like generating events, etc, but it does SetToZero(FCount) too.

Yes, there is no point in zeroing arbitrary integers, but you probably should zero integers which controls access to memory. The same as pointers.

> indiscriminate use of FreeAndNil shows a lack of consideration and intent

I do believe that many people saw a lot of bad code with FreeAndNil. And so FreeAndNil starts associating with lack of design/consideration. But this shouldn't be necessary so. A good code can use FreeAndNil as additional checks.

> Using a call that executes unneeded instructions sends a message to future readers of the code that shouldn’t be sent.

What about Destroy then? Same reason to abandon Free and use Destroy. "Why Free is used here? Why you should check for nil before destroying? Is there a hidden execution path to that Free?". Same reason. Still, nobody ever use Destroy, right? So, is this all about habits?

> And when you are dealing with something as important as memory management

...and I wouldn't lie to machine either.

> FreeAndNil has a clear meaning – it is a very clear indicator that the pointer being freed has meaning outside of the scope where it is used.

Not neccessary.

Is setting FCount to zero in the TList's destructor indicate that FCount can be used in the future? I doubt that anyone will think about it in that way.

So, what's the difference with FreeAndNil then? The difference is that Clear pattern (as seen in TList) is used everywhere, and FreeAndNil is used rarely. So it's all about habits again.

> Losing clarity in your code is bad, right?

Well, same reason to abandon Free and use Destroy. Still, noone do that.

> Thus, if you feel the need to use FreeAndNil to ensure that you don’t misuse a pointer somewhere, then it is very likely you have a design problem.

Yep, agreed. But how do you know that your code is designed all right, and there is NO tiny mistake ever made, no sir, never? Can you PROOF that it's so even after many modifications? Okay, what you do actually lose, if you would use FreeAndNil to almost GUARANTEE this?

>  It’s a much better plan to simply control your scope and never feel the need for it.

Yes. And it's even better to control your scope AND use it. You lose nothing, but gains additional checks. That's the point.

> The real argument is:
> “If your code requires you to use FreeAndNil to reveal and easily find bugs, then your design is wrong.  Good, clean code never feels the need to worry about errant pointers.”

I just don't get it. For some reason, ANYONE who talks against FreeAndNil automatically think that there was no good design done for the code. For god's sake: WHY? Smile  Seriosly.

Alex Russia |

12/14/2011 2:49:39 AM #

Serg

Please don't use shortlinks in the posts. Like FreeAndNil, they make no sense since they are hidden in text, and make the reader confused about the actual URL.

Serg Russia |

1/2/2012 9:41:47 PM #

Lachlan Gemmell

Agreed. I'm always hesitant to click on shortlinks... what's hiding on the other side he doesn't want me to know about?  Wink

Lachlan Gemmell Australia |

12/14/2011 3:03:38 AM #

David Heffernan

Nothing in the blog post here, or the forum thread convinces me that the use of FreeAndNil rather than Free increases the risk of the code containing a defect now or after future maintenance.

I personally wish that the FreeAndNil brigade would stop preaching about it and equally that the FreeAndNil haters would likewise stop preaching. Why does this have to be a one size fits all discussion?

Nick is clearly in a great position because his code would appear to only call Free in destructors, or on a local variable at the very end of a method. But not everyone has code that is so beautifully formed.

David Heffernan United Kingdom |

12/14/2011 2:40:57 PM #

Jolyon Smith

Yep, we can now add "FreeAndNIL" to the list of software development debating club subjects that includes "with" and "goto".

Jolyon Smith New Zealand |

12/17/2011 6:10:01 AM #

Arioch

100 year into future, textbook on computer history would mention Delphi as a historical language, was built to demonstrate issues and accumulate practical arguments for still ongoing debates about the famous FreeAndNil Problem Smile

Arioch Russia |

12/15/2011 8:51:21 PM #

Nick Hodges

David -

You don't have to be convinced, though I naturally think my argument is very convincing. Wink

Nick Hodges United States |

12/24/2011 3:37:58 AM #

Thorsten

As far as I can see, your "argument" is free of any actual meaningful reason to justify your conclusion (which, for what it' worth, I strongly disagree with).

Thorsten Australia |

12/14/2011 3:22:27 AM #

Alex

When you put away a gun, you set the safety AND remove the ammunition AND lock the gun case.

I bet you'd be nervous if somebody pointed a loaded gun at you even though the safety is engaged.

The same here. It's better to have a good design AND use FreeAndNil, then have only good design or only using FreeAndNil.

Alex Russia |

12/14/2011 3:23:16 AM #

Alex

"then have" -> "than have", sorry.

Alex Russia |

12/14/2011 5:31:56 AM #

Marjan Venema

"And if you do use it for defensive reasons, you have to use it everywhere.  You have to use it in ever single place it is needed and you can’t miss a single place.  And, every single maintainer of the code after you has to as well.  One instance of not using it basically removes all the reasons for using it.  It’s a much better plan to simply control your scope and never feel the need for it."

Exactly.

We want FreeAndNil. Not just Free. For defensive reasons. Yes, it would be better to control the scope of your pointers tightly. However, I am not perfect so I want to be slapped on the wrist with  an AV as soon as possible instead of having a bad pointer lurking about ready to create havoc in unexpected places.

And even when I would always get it right, our code is heavily multi-threaded and locks are used only when absolutely necessary to guarantee correctness. Logging and other reporting often do not merit the performance penalty of a lock (or other thread synchronisation methods): we really don't care whether 10.000.000 or 10.000.010 records were read.

When your destructor code is liable to be interrupted half way through cleaning up FreeAndNil serves the very useful purpose of making an instance inaccessible before the destruction even starts.

And so our rule is indeed to use FreeAndNil everywhere and make the uses of Free instead of FreeAndNil stand out like a sore thumb. We are even considering adding a code-grep in our build server to fish out the cases where Free is used instead of FreeAndNil so we can address these...

Marjan Venema Netherlands |

12/14/2011 9:11:08 AM #

David Heffernan

@Marjan You can't expect any code to be resilient to object access whilst the object is part way through a constructor. Doesn't matter when the ref is set to nil, once the destructor starts running you can't support any other thread accessing the object. FreeAndNil won't help you there, it's already game over.

David Heffernan United Kingdom |

12/14/2011 6:42:37 AM #

Radek Cervinka

>We want FreeAndNil. Not just Free. For defensive reasons.
Yes, I agree. Calling only Free is only half part and leave invalid reference.

Radek Cervinka Czech Republic |

12/14/2011 7:22:55 AM #

Nelson Henrique Corrêa Nepomuceno

I think FreeAndNil can be very useful in some situations. See a simple example bellow:

type TForm1 = class(TForm)
:
  MyDialog: TMyDialog;
:
end;

procedure TForm1.btnShowDialogClick;
begin
  if not Assigned(MyDialog)
    then MyDialog := TMyDialog.Create(nil);
  MyDialog.Show;
end;

procedure TForm1.btnHideDialogClick;
begin
  if Assigned(MyDialog)
    then FreeAndNil(MyDialog);
end;

Nelson Henrique Corrêa Nepomuceno Brazil |

12/14/2011 7:57:44 AM #

Daniel Hiromy Moriya

Once, for memory usage reasons, every time my lists were empty, the lists objects had to be freed. Sometimes the design demands the use of FreeAndNIl.

Daniel Hiromy Moriya Brazil |

12/14/2011 8:50:45 AM #

Olaf Monien

I don't use Free, Destroy or FreeAndNil() (not to mention that freaky Release) at all . I simply make sure the systems that run my software have sufficient memory. And of course my code is always (let me repeat: always) well designed and will never have bugs.
That simple! Doh!

Olaf Monien Germany |

12/14/2011 10:15:05 AM #

Daniel Luyo

We use FreeAndNil for defensive reasons.
When you work with many developers with different skills levels I prefer to be sure they did what it's supposed to be done, so we use if Assigned(), and FreeAndNil (or Free + Nil)
Maybe it's not elegant and won't win a beauty contest, but it's effective and help us a lot to pinpoint errors, and no, we are not removing them after debug, that would counterproductive

Daniel Luyo Peru |

12/14/2011 12:52:29 PM #

Allen Bauer

Boy you sure stepped in it here Smile... it's going to take a while to get this off your shoe...

I would like to hear the argument for using FAN on a *local* variable in the common pattern:

allocate
try
finally
  release
end;

Requiring its use in destructors is a little more fuzzy; I still tend to agree that in those cases there *may* be a design issue.

Allen.

Allen Bauer United States |

12/14/2011 1:17:00 PM #

François

IIRC, FreeAndNil was introduced after some push by Ray Lischner who advocated it. And was then recommended in his "Delphi in a Nutshell" (www.amazon.com/.../1565926595):
"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):"

François United States |

12/15/2011 8:52:51 PM #

Nick Hodges

I'd say that Ray needs to update his book.  Wink

Nick Hodges United States |

1/2/2012 9:49:08 PM #

Lachlan Gemmell

I really wish he would. I'll buy another copy even if he were to recommend always calling FreeAndNil twice to make sure it's dead.

Best Delphi book ever!!!

Lachlan Gemmell Australia |

1/2/2012 10:19:32 PM #

Nick Hodges

Wink

Nick Hodges United States |

12/14/2011 1:47:37 PM #

Christian Wimmer

Well, are you sure that your code without setting pointers to nil wil behave correctly? Maybe, your code uses such a pointer still and calls methods on it. And maybe you are lucky most time because the memory itself hasn't been changed. But all of a sudden you get errors because something has changed at another place (maybe due to new code and data in memory). Well, good luck to find the problem in your "good" design (especially after some time).
If nil pointers after freeing are such a "bad thing" -- as I do interpret this article -- why not use deliberately designed ill pointers? E.g. setting the pointer to an address that is invalid like MS VC++ does in debug mode? In such a way, you can't check for NIL, but you get an exception telling you that you logical design is flawed: Learning by crashing.

BTW: I do not talk about pointers that go out of scope and thus are no more accessible.

Christian Wimmer Germany |

12/14/2011 1:59:58 PM #

Nick Hodges

Christian --

"Well, are you sure that your code without setting pointers to nil wil behave correctly?"

Well, yeah, pretty much.  First, I have unit tests for my code to make sure that it works as I design it.  Secondly, I never let the scope of a pointer exceed it's usage, so it doesn't matter if my pointers are nil or not.

" good luck to find the problem in your "good" design (especially after some time)."

That's sort of the whole point. I don't need any luck finding the problem because the problem never happens.

"BTW: I do not talk about pointers that go out of scope and thus are no more accessible."

Neither do I, hence the complete lack of need for FreeAndNil

Nick Hodges United States |

12/14/2011 4:55:23 PM #

David Heffernan

"First, I have unit tests for my code to make sure that it works as I design it."

Don't kid yourself Nick, your unit tests do nothing of the sort. You can't write perfect unit tests. Nobody can. If you could write perfect unit tests then you wouldn't bother, you would write perfect code that would not need testing.

Since unit tests are code, do you write unit tests for your unit tests.

David Heffernan United Kingdom |

12/15/2011 2:51:04 AM #

Alex

> First, I have unit tests for my code to make sure that it works as I design it.

So basically you're saying "I don't know that, but I check this with unit tests" Smile

Alex Russia |

12/15/2011 8:29:31 AM #

Dean Hill

I can't see this happening in a completely decoupled solution. If you are accessing code from a different library then this will typically done through an interface so FreeAndNil is not an issue there and within a class you should not find yourself in this situation as there are only two types of objects you will be using within a single class; temporary local ones and objects that you can easily manage within the class.

Dean Hill South Africa |

12/14/2011 2:23:32 PM #

Mason Wheeler

Your "scope" argument makes the implicit assumption that a given variable will only ever be used once.  When this is not true, there's a legitimate use case.

In my game engine, I've got an array of rather heavy objects that are lazy-loaded.  When you ask for one, it checks to see if the slot in the array is assigned or not, and loads it if it is.  (The object represents the entirety of a level, so loading them all up-front would be a bad idea.)

When you leave a level, depending on various considerations it may or may not unload the level from memory.  When it does, it calls FreeAndNil on the appropriate slot in the array, because that's the correct thing to do in this case: free the level, and set its reference to nil to indicate that it's no longer loaded.  The "scope" of that level may be finished, but the scope of the engine itself, which manages all levels, is not.

Mason Wheeler United States |

12/14/2011 4:46:22 PM #

David Clegg

The lazy loading scenario is similar to where I've often used FreeAndNil before. An Assigned check on a lazy loaded object which may need to be refetched (and therefore invalidated) later on. Using FreeAndNil makes sense to me in this situation, but I'm opening to hearing why it doesn't.

As an aside: I'm not a big fan of "You should never use <certain language construct>". Never is such a final word, and often doesn't cater for all scenarios. Its often used when the point the author is trying to make is actually "Using <certain language construct> in <common usage pattern> is not a good idea".

David Clegg New Zealand |

12/14/2011 4:47:47 PM #

David Clegg

<blush>Opening=open

David Clegg New Zealand |

12/15/2011 8:46:37 PM #

Nick Hodges

Mason --

"Your "scope" argument makes the implicit assumption that a given variable will only ever be used once.  When this is not true, there's a legitimate use case."

That is true, but that is because I'd consider using a variable, particularly a reference variable, more than once a very bad practice and a strong code smell.  Such a thing is screaming out for the Extract Method refactoring if done in a single method, for instance.

Re:  your array of levels:  I don't know enough about your code, but it sounds like an interesting construct -- but one that seems a bit "smelly" to me.

Nick Hodges United States |

12/14/2011 2:49:46 PM #

Captain Jake

I think this whole discussion is like trying to figure out whether you should use wooden or metal wheels on your buggy. Reference-counted interfaces are what you should be using anyway, keeping your actual class implementations private and hidden in the implementation section of their unit. There is this thing called Object Oriented Programming, some of you may have heard of it?

Captain Jake United States |

12/15/2011 12:12:22 AM #

Mason Wheeler

Yeah, I've heard of it.  Funny how they named it "Object-oriented" and not "Reference-Counted-Interface-oriented."

Interfaces have their place, but treating them as a magic hammer is just plain ridiculous.  (Especially when they're all reference counted, and then you end up with circular reference problems all over the place!)

Mason Wheeler United States |

12/15/2011 8:49:42 PM #

Nick Hodges

No one called Interfaces a magic hammer, Mason.  

However, using interfaces is a powerful technique to ensure loose coupling and clean code.

Nick Hodges United States |

12/15/2011 8:48:54 PM #

Nick Hodges

Well said, Jake. If you program against interfaces and not against implementations then FreeAndNil becomes moot.

Nick Hodges United States |

12/14/2011 2:51:28 PM #

Ajasja Ljubetic

I don't really feel that strongly about FreeAndNil, but please, please *do not* use short links in blog posts. They really serve no purpose other than to obfuscate the text.

Ajasja Ljubetic Slovenia |

12/15/2011 5:47:49 AM #

Uli Gerhardt

You can try http://www.longurlplease.com/ to get rid of tinyurl etc.

Uli Gerhardt Germany |

12/14/2011 4:14:55 PM #

Nick Hodges

Ajasja --

I use bit.ly links because I like to track the things people click on.  I'm sorry if you don't like them.

Nick

Nick Hodges United States |

12/29/2011 8:53:24 AM #

EMB

Some people just don't click when they see a short link. It's like the use of FreeAndNil.

EMB |

12/14/2011 4:37:01 PM #

Alister Christie

Could one use a set of similar arguments that unit tests are a bad practice?

Alister Christie New Zealand |

12/15/2011 4:48:46 AM #

Mykhaylo Skachkov

this is exactly the case. strong typing too, btw

Mykhaylo Skachkov Ukraine |

12/14/2011 4:58:28 PM #

Olaf Monien

@Alister Good point! Unit tests are for wimps! Smile

Olaf Monien United States |

12/15/2011 3:37:21 AM #

Daniel Bernhard

I've heard the argument "I never let the scope of a pointer exceed it's usage" quite a few time.

And then I've seen quite a few time that there were two pointers to the same object. The object get's deleted sometime and only one of the pointers is discarded.
The other one still is used and if you're unlucky enough, everything works fine because the memory is still in its original shape.

After having traced down numerous of such problems I'm a bit paranoid about leaving dirty pointers around...

BTW: anyone who thinks that reference counting interfaces would be better: FreeAndNil uses less time than setting an interface pointer to nil. Even more so if the reference count uses a locking mechanism (and you wouldn't use any other reference counting mechanism, would you?)

Daniel Bernhard Switzerland |

12/15/2011 8:54:58 PM #

Nick Hodges

Daniel --

The notion of two pointers referring to the same object makes my skin crawl.  

I definitely think the use of reference counted interfaces is *vastly* better than coding against implementations.

Nick Hodges United States |

12/16/2011 3:56:20 AM #

Daniel Bernhard

Let's assume you have a multi-threaded application where you need to share some objects between multiple threads.
Fact is: with reference counting interfaces you NEED exclusive access in such a scenario. So EACH TIME you COPY an interface pointer you need a lock. Even with a lightweight exchange mechanism you still have way less performance than a "normal" counter.

Point is: we're component developers. I cannot disregard the possibility that some of our classes will be used in a multi-threaded fasion.

So you now propose to rather waste all that performance than to employ a good design?
We'll... I hope you don't expect me to agree...

Just to make it clear:
I agree that implementing "service like" stuff through interfaced can be greatly help a good design. But making everything a service isn't a solution either (or do you propose to replace all controls and components with services too?).

Daniel Bernhard Switzerland |

12/16/2011 11:12:17 AM #

Nick Hodges

I always love a good "reductio ad absurdum" arguement.  Wink

Nick Hodges United States |

12/17/2011 6:00:48 AM #

Arioch

But FreeAndNil cannot save you from copied pointers.

The heap MM, always wiping the freed memory block, probably can.

Arioch Russia |

12/15/2011 4:48:04 AM #

Mykhaylo Skachkov

Nick, do you lock door when you leave home and go to work? I'm sure you do. But lets think if it is something that you have no way to avoid? Instead of locking you can improve your relationships with people around and no one will ever go inside to steal smth. I mean when you move to new living place, you can work on relationships from the beginning and so you can be sure that no one goes inside your home when you're out.

Now just think a bit and extrapolate above example on FreeAndNil usage. When you call FreeAndNil (lock the door) this gives your certain predictability of latter behaviour - because you get AV _right in place_ if there is incorrect using of the pointer (you know that something has been stolen - as you see your door lock is broken). Otherwise you have no idea what went wrong (if you miss some thing you never know whether you just lost it, forgot where it is or it has been stolen).

In other words the parallel between door lock and FreeAndNil is strict (in terms of subject being discussed of cause). There are ways to leave with unlocked doors but everyone locks them Smile Why? Just because it decreases risks.

Thus using FreeAndNil is a good practice. Should you use good practice? Its up to you. But if you would, it would make you life easier regardless of overall design.

PS. you can also avoid using (strict)private, (strict)protected as well and have no problems. In theory Smile

Mykhaylo Skachkov Ukraine |

12/15/2011 7:38:23 AM #

Peter J. Rosario

Nick is smart to bring up scope in a discussion of FreeAndNil().  I would use FreeAndNil() less if Delphi gave me better control of scope like other languages do:

procedure DelphiCantDoThis();
begin
    DoSomething();
    begin
        var Obj : TObject;
        Obj := TObject.Create();
        try
            Writeln(Obj.ClassName);
        finally
            Obj.Free();
        end;  (* try..finally *)
    end;  (* begin *)
    DoSomethingElse();
end;  (* procedure DelphiCantDoThis() *)

There would be no need to use FreeAndNil() on Obj since there would be no way to use Obj at the point in the code where DoSomethingElse() is called (or even where DoSomething() is called).

Peter J. Rosario United States |

12/19/2011 7:47:36 PM #

David S


After spending 10+ years working with c++, this would be a wonderful addition to the Delphi language!

c++ programmers love the ability to declare variables at the point where you want to use them.

I don't understand why it's not possible in Delphi.

David S United States |

12/15/2011 7:50:02 AM #

Alex

Let's change Delphi compiler to make Free a magic function, which set variable to nil after deleting object (not possible for expressions). Thus, both camps will be satisfied (FreeAndNil camp will use Free, because they really just want clear pointers).

Smile

Alex Russia |

12/17/2011 5:55:29 AM #

Arioch

1) i just read blogs.embarcadero.com/abauer/2010/02/05/38910 and i like the idea of FreeAndInvalid as opposed to FreeAndNil

2) adding magic functions and other exclusions to compiler is not nice IMHO. However making some generic construct allowing instance method to operate on the variable rather than reference would be interesting idea. Like by-reference out-parameters vs by-value in-parameteers of subroutines.

3) memory manager explicitly wiping the freed memory would probably do the same for "crash early". Though it would not highlight values in Watch Local Variables debugger panels and such. And it is much more flexible. Just consider i made a caching 1nd reference to the object, contained deep withing some mega-object. Now i free (or even free-and-nil) the container. The caching 2nd reference was not nilled anyway.

Arioch Russia |

12/17/2011 5:48:40 AM #

Arioch

> FreeAndNil is a function declared in the SysUtils unit and was introduced in Delphi 4, if I recall correctly.

in D5
it was discussed at the very dawn of The Thread

You could just search for "introduce" keyword.

Arioch Russia |

1/5/2012 1:49:57 AM #

Qian Xu

Good software design does not have such kind of problems. If developers try to avoid problem by using FreeAndNil, the code will never look maintenance-able.

BTW: Defensive programming is recommended. And I don't think 'if Assigned(some_object) then ... else raise SomeException' is good. Usually I would rather put some preconditions, such as 'assert(some_object <> nil)'. It will make developer more easier to focus on real code logic, not on any unexpected exception handling.

Qian Xu People's Republic of China |

Pingbacks and trackbacks (1)+

Comments are closed

A Pithy Quote for You

"You cannot increase the water in a swimming pool by taking water from the deep end and pouring it into the shallow end."    –  Me

Amazon Gift Cards

General Disclaimer

The views I express here are entirely my own and not necessarily those of any other rational person or organization.  However, I strongly recommend that you agree with pretty much everything I say because, well, I'm right.  Most of the time. Except when I'm not, in which case, you shouldn't agree with me.

Month List