Category
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 nil
.
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.
Why typesafety
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…
That is no longer the case with newer Delphi versions. A FreeAndNil on an interface or record variable is caught by the compiler.
That's the type safety I was…
That's the type safety I was talking about.
I agree...but
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;
try
x.Add(myParam1);
x.Add(myParam2);
DoSomething(x);
finally
x.Free;
end;
Never call Destroy!
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.
Correct, in that particular…
Correct, in that particular code snippet provided, what is the benefit of calling Free instead of Destroy? (Why wouldn't you call Destroy instead of Free in that scenario?)
This would seem to follow along with your exact advice for FreeAndNil:
"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."
Unrelated
I don't see these two issues as related. Calling Destroy
is explicitly forbidden in the documentation and it's been that way ever since Delphi 1 (I just checked in my copy of the first edition of Delphi Developer's Guide). But FreeAndNil
is a convenience that wasn't introduced until Delphi 5.
Since calling Free
does a check before calling Destroy
allowing you to call Free
multiple times without error it can therefore be considered in the same discussion as whether or not to use FreeAndNil
which is frequently the basis for a similar check in the user's code but there's still a big difference between a core tenet of the language and an optional procedure.
It's not going to move…
It's not going to move anyway when you leave it in gear (or Park).
My personal opinion is that it isn't the transmission's responsibility to stop my car, or to keep it stopped. That is the job of the braking system.
It's already stopped
In my analogy, the transmission is not stopping the car, it's keeping it from moving from a stopped position. Assuming the car is stopped and in gear (or Park), adding the emergency brake is superfluous (most of the time) and my argument is that using FreeAndNil is equally unnecessary (most of the time).
Add new comment