When freeing an object in Delphi, simply calling its
Free method calls the object's
destructor and releases the memory allocated to the instance of the object. But it doesn't change the address of the referencing variable which, therefore, still points to the place in memory where the object existed. The released memory can be quickly reused by other objects or resources and if you try to access the object again without re-creating it, you could get an Access Violation or some other error or worse yet, unpredictable behavior. Of course, it would be silly to purposefully access a freed object but sometimes you inherit messy code and don't totally understand when or where objects are created and freed. In some cases, programmers take one additional step after freeing an object--and that is, setting its reference variable to
This practice of "nilling" an object reference was so popular that back in Delphi 5, a procedure was added to the
SysUtils unit called
FreeAndNil which does exactly as the name suggests. Soon after, there erupted a debate as to whether you should use this procedure always, sometimes, or never. Proponents for it say it's a safer way to program; those against say if you design your code well, you should never need it (long read). In Delphi 10.4, type-safety was added to the procedure.
The debate continues--and will be discussed next week. It should be a lively webinar!
My purpose here is not to add any arguments for or against but simply to state where I stand: I seldom use
FreeAndNil. Note that I didn't say "never" but I rarely need it.
My personal opinion is that frequent use of
FreeAndNil is lazy programming--you're not really thinking about when your object variables are in use and you're constantly checking if they're nil before you use them because you didn't take the time to limit their scope or carefully construct the flow of your application in such a way you know whey they're created and freed.
It's similar to using the emergency brake when you park your car on level ground. It's not going to move anyway when you leave it in gear (or Park). I think about whether or not I really need to use the emergency brake and only set it when parking on hills. Likewise, I only use
FreeAndNil when I know I'll need to check the status of an object variable later. Sure, I could set a Boolean flag or use some other way of knowing whether or not I need to create an object but sometimes it's just more convenient to check the object variable and set it to nil when it's freed.
My advice: Think about your code. Know the status of your objects. And use
FreeAndNil sparingly but intentionally.
The only problem with using FreeAndNil(MyObject) rather than just MyObject.Free is that if you later on change MyObject from an object instance to an interface or a record, your code will still compile but you will get very odd runtime errors. That's why adding type safety to FreeAndNil was a good thing.
That is no longer the case with newer Delphi versions. A FreeAndNil on an interface or record variable is caught by the compiler.
I agree... but for the sake of discussion, change your key sentence to this with one word altered: FreeAndNil changed to Free:
"My personal opinion is that frequent use of
Free is lazy programming--you're not really thinking about when your object variables are in use and you're constantly checking if they're nil before you use them because you didn't take the time to limit their scope or carefully construct the flow of your application in such a way you know whey they're created and freed."
For this discussion, we are ignore the use of Free in destructors which is expected...instead, consider the following code snippet that you have probably seen a million times. What is the benefit of using Free here - why shouldn't you use Destroy?
x := TStringList.Create;
Are you saying that instead of calling
x.Free you should call
x.Destroy? We are never supposed to call Destroy directly.
And for your initial argument, my point is that
FreeAndNil is lazier than
Free by itself because the latter requires you to know if an object has been freed instead of simply checking to see if it's nil before reusing it.