You are familiar with FreeAndNil(), but do you use it? How often? Are you using it right? As with most things in software development, it is a complicated topic. So let’s see what the experts have to say. We are going to debate the details in a friendly discussion with some of your favorite MVPs.
- This blog post will include the replay, slides, and more after the webinar.
The Survey Says…
When you register for the webinar we’ve included a short survey to see where you stand on the issue. During the webinar we will compare the general consensus with that of our MVP panel of experts.
Even more MVPs have weighed in on the topic and I have some teasers for how they voted…
I’ve left the legend of that the charts mean off for now, you need to join the webinar to see the details, but the use of FreeAndNil() is pretty evenly split if we lump the responses into generalities for for and against.
If we break things down into details though it is a little bit more nuanced. Again, without the legend, yet.
Making assigned checks is similar, but a little more pronounced differences.
- Q: I have a motto: if you created something, destroy it at the end of the routine! That is why I use FreeAndNIl() a lot!
- A: It’s not always possible, but I see your point.
- Q: Instantiation on demand is often a sensible pattern, and so you won’t have anything to sit in your pointer!
- A: Nice point
- Q: Does this guy do any real programming?
- A: yes, a lot of it.,Yes, he’s an extremely experienced coder and well respected. I promise you 🙂
- Q: Call you Dummy object “Nil” 😛
- A: Good point.
- Q: I sit corrected.
- A: lol
- Q: nil is a great way to confirm that there’s not anything referenced, and if you ALWAYS free with FreeAndNil then your code will self maintain that the pointer will be nil if it’s not valid, otherwise it’s always a valid object.
- A: It does asign nil, but there are times when you don’t need to asign it to nil, or when you might be obscuring somethings else.
- Q: How can you say “always use interfaces” and then also say “you should never destroy something you haven’t created” – completely inconsistent!
- A: I said, “if you can, use interfaces” and the point about coding to an interface is the reference counting is explictly designed to deal with this.
- Q: There are tons of use-cases for Assigned and FreeAndNil. If you are not using them, you either aren’t using such use-cases, or you are a bad programmer. To say that there is no reason to ever use them, or that if you are using them you should not be, is so completely wrong.
- A: I believe what Nick is saying is that using FreeAndNil and Assigned checks are a code smell that you might need to take a different design. Also that the overuse of FreeAndNil obscures things too.
- Q: There are many circumstances when the code responsible for freeing an object is not the same code that created the object. The most obvious example is a reference counting memory management model.
- A: sure
- Q: Should also get a C++ dev view
- A: Yes, some of the MVPs use both.
- Q: F# uses the Option type (union type with Some and None) to avoid nil, and I believe this requires support in the language (in the type system). Does Delphi provide this kind of support?
- A: not that I’m aware of…
- Q: Why would you ever free an object, and not set the pointer to it to nil?
- A: If the reference isn’t going to still be around because it is going out of scope immediately then the assignment isn’t necessary.
- Q: What Olaf just explained has a name: Cargo cult programming
- A: That was a concept I was thinking about coming into this webinar. I’m a big beleiver in evidence based programming. ,Tbh, I had to look up what “Cargo Cult” means. Yes, I agree. But like I said, if you are on your own road, or there are safe drivers, then FreeAndNil() is of now use. What I see in the wild, is way different though. Remeber, I am frequently working with external teams, with very different skill sets. Many of them not having the “Save Driver” tag (yet)
- Q: The wikipedia article even has this statement: “Obsessive and redundant checks for null values or testing whether a collection is empty before iterating its values may be a sign of cargo cult programming.”
- A: lol
- Q: We use property getter methods that include checks for assigned of an “f” variable and will construct it on demand… sometimes the construction of that “f” variable has ramifications (say a request to a database or a form construction) so we do not construct every “f” variable ahead of time. And we freeandnil to help guarantee subsequent calls to the property are managed and initialized appropriately.
- A: sure
- Q: FreeAndNil simulates C++ unique_ptr local variables. Delphi 10.4 has finally introduced RAII, so there can be a more explicit unique_ptr stuff now, but I have to maintain Delphi 7 code, and so I keep using FreeAndNil as unique_ptr which is missing
- A: It is always frustrating when I have to work with code for old compilers too.
- Q: “There’s no harm in leaving a pointer set to an object that’s been freed” – really? Have you ever had to debug anything?
- A: Right,don’t agree with the kind of specious denigration of the programming skills but I do see what you are saying which is “it can cause problems with the debugger so you disagree”
- Q: maybe you should explain the exact difference between x.free and FreeAndNil(x) I think not all here are aware of the difference
- A: FreeAndNil(x) free’s the object, the same as x.free, but it also sets the reference to nil. If you don’t set the reference to nil, then it will still be pointing at the freed object.
- Q: A class field that references an object should be nil until the object is created, and when the object is freed it should be put to nil. This conversation is nonsensical to me.
- Q: Code examples?
- A: If you look at the slides there are a couple blog posts that link to code. https://developpeur-pascal.fr/faut-il-vraiment-utiliser-freeandnil-dont-nos-programmes-en-pascal.html https://corneliusconcepts.tech/delphi-debates-freeandnil
- Q: I really do not understand the reason for this debate. I thought it was going to be explanation as to why FreeAndNil should be used instead of using .Free and then := nil. Here we seem to be discussing using FreeAndNil on objects that I never created. I think I have lost the plot!
- A: The discussion is the pros and cons of using FreeAndNil and having unassigned references.
- Q: I have developed SafeMM3 and found bug in FireMonkey. Destructor used “Free” for a reference which is supposed to be gone since it’s destructor after all, but then some SetFocus operation was walking dangling pointers. You can rarely be sure that the last operation on reference is really the last.
- A: good point.
- Q: The point is that NIL is a real true value in code, and for that reason one will check for those situations (like rejecting a NIL as Nick states), and as such NIL do not go away, so it makes sense to NIL something to ensure that the memory is indeed NIL and not some random old value from old days. This is specially important when you write lowlevel high performance code, but obviously much less important when one primarily is writing high level code, essentially scripting existing modules together. Interfaces absolutely have many great uses, but sometimes we need simply pointers to records or classes, and there keeping track of NIL or not NIL is quite critical. Therefore FreeAndNil have its uses, but so do x.Free; and x:=nil; If the later fails, then FreeAndNil may fail and we are talking about a multithreaded scenario, where more care of handling concurrency correctly is important.
- A: Nice point Kim.
- Q: Wrong. You should not always create a classes in its constructor. If is common to create the object on its first use, and then leave it created for reuse.
- A: I can see there are quite a few people taking both sides of this point of view.
- Q: Null object pattern (that is what Nick called dummy object) is ok for injectables, but not for many creatables
- Q: Recently I had bad a crash because of accessing a freed object that was not nil. This is really hard to detected. If the variable gets out of scope, nil is not really required, but you have to check the code very carefully to avoid using it afterwards.
- A: In my opinion, if there is a chance your reference is still used later, then you should assign it to nil with FreeAndNil.
- Q: Action := caFree When I do this do I have to put a nil pointer? MyClass := TMyClass.Create; MyClass := nil when I use Action := caFree
- Q: The key question should probably be… is there a true DOWNSIDE to using freeandnil?
- A: Obscures things and can introduce errors with lazy initialization.
- Q: Using Interfaces is not normally about memory management, mixing the two (with the lack of explicit documentation) is a whole series of disasters waiting to happen. I have seen lots of code holding interface references to objects that were freed when the reference count went to nil. A memory management discipline of always explicitly freeing with FreeAndNil seems that it must be inherently safer.
- A: perhaps
- Q: I think that on a multithreading application it makes sense to use Assigned() and FreeAndNil(), when instances can be used temporarily or interactions with remote services/servers can get interrupted and need reconnections with these temporary instances.
- A: Yes I think several of the MVPs agree with you.
- Q: Ada.Unchecked_Deallocation works like FreeAndNil out of box. Same goes to procedure Delete, it destroys the passed cursor. Too bad Delphi developers rarely look into other Pascal descendants for inspiration
- A: I think there are much more investigations into the techniques and innovations of all languages – not just Pascal descendants – that you might realize. For example, inline variable declarations (which I personally hated when they came out) are inspired by other languages which did this. They are very ‘un-Pascal’ but turned out to have some very distinct advantages which were too compelling to ignore.
- Q: You should not always create all of a class’ objects in its constructor. If is common, at least for us, to create the object(s) only if and when they are needed, and then leave them created for reuse. Then when the class is destroyed, it should destroy the instances created. Assigned and FreeAndNill are vital for this.
- A: Lazy initialization, yes
- Q: Have to drop, but great discussion!
- A: Thanks Gary.
- Q: For today’s computers, the CPU cycle(s) for FreeAndNil are insignificant, even for 3d engines or whatever. This isn’t 1980!
- A: as Nick and Thomas pointed out, it requires the developer to consider why FreeAndNil, so it takes more developer cycles.
- Q: estou aprendendo a desenvolver aplicativo mobile através do delphi 10.4 CE FMX, e, tenho muitas dúvidas e não encontro em lugar algum, a não ser nos grupos de telegram ou nos vídeos do 99coders – que tem uma didática fantástica, além de Márcio, Gledson Prego, Anderson Fiori e MobiusOne, que tem nos ajudado e muito. Mas, isso é pouco para uma aplicação tão antiga como o Delphi. Minhas dúvidas são: 1) Qual é o método correto e onde destruo os objetos(*) que são instanciados numa function/procedure na seção VAR? (*)jsonarray, jsonobject, frame, etc… >> 1a) esses objetos os destruo com o FreeAndNil, disposeOf, .free, =nil? >> 1b) qual é o melhor e mais eficaz método de destruição desses objetos? >> 1c) onde é o local (event) correto para destruição deles? onClose, onDestroy? 2) Por que o delphi causa muitos Memory Leaks de objetos que a gente tem certeza que eles estão sendo destruídos?
- Q: This is a great session (Marco)
- A: Yes, it seems popular.
- Q: Could you expand on why FreeAndNil() is not threadsafe?
- A: It isn’t atomic. You should lock the reference before the call to FreeAndNil.
- Q: “Dangling Pointers” – a co-operating memory management model needs to ensure that consumers of objects are notified when an object is freed.
- Q: FreeAndNil sets to nil before it frees – so while you may have a context switch before you have freed the object, you will have already set the pointer to nil …
- Q: If freeing is the last action, then Free(). If one variable is used multiple times, then FreeAndNill()?
- A: if you are going to reuse the reference then FreeAndNil
- Q: What does FreeAndNil actually do? Why doesn’t .Free set the reference to nil?
- A: Free checks the reference to see it is assigned, and if it is, then it destroys the object, but it still references the destroyed object. FreeAndNil additionally assigns it the reference to the nil.
- Q: Sadly inline variables do still not work. if you use the reference search oder refactoring tools “after” a inline variable in a unit it breaks these tools 🙁
- A: There is some more work and RSPs in connection with refactoring and inline variables. The refactoring (and thing slike auto reformatting) can be a problem for newer language constructs.
- Q: The one specific advantage Pascal had over C based languages… the requirement to declare interface section AND variables before usage. The way that makes it possible to actually get an overview of code just by glancing it.
- A: yes
- Q: Find my project SafeMM3 on OSDN. Unlike SafeMM and SafeMM2, it is compatible with recent Delphi, tested on Delphi 10.2. I have found dangling pointers in FireMonkey, produced by naked Free
- A: watch out for dangling pointers.
- Q: And then that advantage was “compromised” by inline variable declaration and even datatype deduction…. Brzzzzz….
- A: I love inline variables.
- Q: Where are the examples?
- A: I posted some links above.
- Q: lembrando, estou vindo do clipper/harbour por onde comecei aos 14 anos de idade e fiquei lá até 2021, onde estava desistindo e assisti a um vídeo impulsionado do 99coders falando do Delphi, onde o título era algo assim: “o delphi morreu?” e ele mostrava que dá para fazer muita coisa via delphi, principalmente para mobile (android/ios) rsrs
- Q: How do you do when using DLLs and passing objects as a parameter? Do you make a copy of the object and send it back as a result object?
- A: It depends I suppose.
- Q: mais uma pergunta aqui de alguém do Brasil: 3) porque tentaram usar o .DisposeOf se teve que voltar pro FreeAndNil( )
- Q: C++ – I have a C++ background which is why I have found the lack of explicit documentation around Delphi interfaces so infuriating.
- A: ah, yes
- Q: 4) favor dar um bom exemplo de uso do freeAndNill() de forma eficaz a não deixar nenhum Memory Leak …
- Q: These points bring up the ownership / borrow ideas in Rust
- A: Yes, Rust got a lot of inspiration from Delphi.
- Q: I don’t have a question, but I want to thank you for the development of Delphi. Thank you)
- A: Thanks! I’m glad Delphi is here too!
- Q: what is a good source for understanding the interface design structure
- A: I believe Nick Hodges’ books discuss it
- Q: Interfaces are not thread-safe. Only the ref counter inside of TInterfacedObject is. But interface assignment is a non atomic operation and would need to be under a lock.
- A: Yes Dalija’s book discusses this at length.
- Q: There was a comment about “wasting CPU cycles”… How many assembler instructions are required for “x = nil”? If this is done on multiple objects in some kind of cycle/loop, assigning NIL might impact performance if the variables are no longer referenced after freeing them, but if the variables might be referenced outside the loop later, it’s better to know if they are really referencing an existing object.
- A: Check the CPU view and see.
- Q: MISRA C is all about cargo cult programming. C allows single-line statements, but MISRA C prohibits them. So it is a pretty industrial practice. Nothing to be ashamed of
- A: ah
- Q: Nice debate!
- A: It has proved to be a lot more popular – and divisive – than we thought it would be!
- Q: @Nick, if you consider never to use FreeAndNil(), then in event based applications (not so rare), how can you avoid to create objects at unknown moments, and avoid to create them twice or more? The typical case is the when the user clicks on a button, and run some TThread descendant. What about if the user clicks twice on the same button, the 2nd time when the 1st TThread launched by the 1st click is not finished.
- A: Maybe prevent the button from being clicked twice? That seems like a valid concern.
- Q: I managed to instantiate an object using “assigned” I only freed the object from memory with “action: caFree” but I didn’t point to “nil” how is this possible?
- A: Unless you call FreeAndNil, or explicitly assign it to Nil, then free doesn’t nil the reference.
- Q: example, where FreeAndNil will show mistakes in code: With object.Free you won’t get an exception if you accidentally use the object. with FreeAndNil(object) you will get the exception immediately!example: procedure TForm1.BT_Click(Sender: TObject); var sl: TStringList; begin sl:=TStringList.Create; try finally sl.Free; //FreeAndNil(sl); end; // — // other stuff // — if (sl.Text = ”) then sl.Text:= ‘Hello World!’; end;
- A: thanks
- Q: Is there a situation where i need use a freed object? (more often I need to “Nil” a var without free the object). Or, perhaps, FreeAndNil exists only for completeness because x.free couldn’t “Nil” the var. Thanks
- A: In my opinion, I FreeAndNil when there are other references that might references it after it is nil.
- Q: No code is bug free. You want bugs to fail early and hard. FreeAndNil helps catch “use after free” bugs.
- A: true
- Q: I never call the destructor directly, that’s the job of Free, isn’t it?
- A: yes
- Q: I almost always use freeandnil on 3rd party components, never trust other people’s code 😛
- Q: I am not sure if directly calling Destroy is actually faster than using Free. Simply because Destroy is a virtual method call. Someone has to provide some benchmark to prove that point
- A: true
- Q: Creating object at their first use can create a lot of problems when trying to do someting with that object. I experienced this when adding some functionality to the InplaceEditor of a TCustomGrid.
- Q: The ideal would be to program so that the compiler helps pick up issues … a lot of discussion here is about programmer skill instead.
- Q: Global Form references – the IDE will automatically create a global pointer to forms …
- Q: So are you calling the IDE Crazy? In from of Jim? That’s just rude!
- A: 🙂
- Q: Speaking about “un-Pascal” inline variables, Ada since the inception has declare-begin-end block. So it is not “un-Pascal”, it’s just you not familiar with Ada yet. But Ada does not end on this. Delphi had just recently got “inline vars” while in Ada developer more often actually enjoys “inline constants” instead. Indeed, if something is initialized in a beginning of a block, chances are it won’t ever change until the end of scope. Marking “constant” stuff aids readability and reasoning
- A: Ada != Pascal. 😉
- Q: If you persistently use FreeAndNIL, then there’s no additional developer cycle when it is used. It’s only when you’re not consistent in your usage…
- A: I suppose that is a valid point.
- Q: Am I allowed to say how much I have enjoyed this thought-provoking discussion? Thank you!
- A: glad to hear it.
- Q: Which books of Dalija Prasnikar would you recommend regarding today’s subject?
- A: https://dalija.prasnikar.info/delphimm/index.html
- Q: I’ll throw my two pennies worth in the ring…. with statement… try not to use them and certainly do not use them for more than one thing ….. just MHO
- A: Yes this is my opinion too – but not everyone agrees, apparently – hence the debate.
- Q: qual usar então para destuir: .free disposeOf =nil freeAndNil() ??? qual realmente libera memória e a gente fica livre da porcaria do “Memory Leak”? obs.: delphi 10.4 CE / FMX / Mobile
- Q: What is Dalija’s book called?
- A: https://dalija.prasnikar.info/delphitspatt/
- Q: This webinar has been great. I’ll be honest I wasn’t expecting much, but quite frankly this has been one of the better webinar’s of late…. More of the same please !!
- A: Noted. Glad you enjoyed it.
- Q: Never used FreeAndNil. Never will – unless Nick starts using it 😀
- A: ah
- Q: A very interesting discussion about dealing with pointers variables…. I usually dispose or return the pointers to memory after using them
- A: Yes. That’s a pattern.
- Q: Totally agree with Holger’s suggestion: please can Delphi stop making a new app with a form built around globals? Certainly worth a debate.
- A: I’ve thought about this too.
- Q: link fornecido por vocês não funciona: https://developpeur-pascal.fr/faut-il-vraiment-utiliser-freeandnil-don’t-nos-programmes-en-pascal.html – este link não funciona (404 error)
- Q: Thanks, enjoyed the session!
- Q: Suggest keep and publish the chat too
- Q: Have to run. Thanks a bunch!!! Great job.
- Q: Destroy alone is quicker than Free. The implementation of Free is “IF Assigned(Self) THEN Destroy;” so by calling Destroy directly, you’re omitting one CALL and one “If Assigned” check – you’re still calling the virtual Destroy…
- Q: If you want to check thread safety of interface stuff, write TInterfacedObject descendant which is invoking Sleep(10) in AddRef and Release. I have written lock-free references with Compare-And-Exchange primitieve which is passing this test. I can probably make thread-safe weak reference too
- Q: sinceramente, os nobres “gurus” não responderam a nenhuma de minhas perguntas. São 11 homens e mulheres que são os crânios da Pascal / Delphi e eu que estou começando e vindo do clipper / harbour, gostaria da vossa atenção, até mesmo para eu me sentir em casa!
- Q: I always try where possible to create the object and free the same object within the same routine, that way I have much more control and far less chance of memory and reference issues and r
- Q: We talk a lot over the years of use of interfaces for automatic memory management … what about managed records now? Can we do RAII in delphi … is there another path ?
- A: yes, RAII does introduce that.
- Q: if you were to compile the questions and answers that are being asked and publish them would be excellent.
- A: Will see about doing that.
- Q: I joined a little late, sorry if that was askeddiscussed before; if you get the child object like in (ParentObject.childObject) freed in anyway, and then you freeAndNil parentObject … can this be not safe because of the time needed to free each object may intersect,, and being sequential?
- A: Good question. Even if you nil the reference the object will still be responsibile to free it’s children, while the children uses a notification pattern to notify the parent when they are freed.
- Q: If you launch a thread on a button click, seems obviously that you should be prepared to run multiple threads :-), you won’t free shared objects in such thread. Or … you disable the button.
- A: yes
- Q: how much more expensive is FreeAndNil to manual Free followed by manually assign free?
- A: CPU wise it does not require much, but what is it communicating.
- Q: I enjoyed that vivid discussionn of really programming experts
- Q: The Delphi RTL uses GOTO 🙂
- A: yes
- Q: Thanks, more about these please. +1
- A: sure
- Q: If you destroy a TJSONObject does it also destroy all the “GetValue as TJSONString” objects?
- Q: Suggestion … can we not just have “don’t use with” … let’s have what it tried to do … what other languages have … and what we could start to do instead with modern delphi in that direction
- Q: Aren’t button clicked events delivered as a result of being GetMessage’d from the UI thread queue? The second click event is not going to be delivered until the first one has been processed, unless it is produced programmatically which would be a reentrancy problem. What am I missing here?
- Q: More goto in the RTL since I started optimizing some System functions without doing asm 😉
- Q: It is not that simple to just disable button, because stuff is more complicated. I use such thing as “demand” from functional programming. So when the first time the button clicks, the reference-counted demand is created, dedicated to “the first click”. The thread can then do some stuff and poll its own “demand” to check if it’s still demanded. And having entered Synchronize, also check if this specific “demand” is still in place. When the second time the button clicks, old demand is marked as obsolete and new demand is deployed. This way first thread gets the message: go away, we don’t need you anymore
- Q: Wish: Local, static, variables that survives across calls (currently use assignable, local CONSTs)
- Q: Thank you