Jump to content
Paul Dardeau

Guidance on FreeAndNil for Delphi noob

Recommended Posts

Thanks, its clear then, how the capture of anonymous methods work.
We came from the question how FreeAndNil might be helpful here, in this kind of situations, right?
Aren't there any situations where FAN can be useful, perhaps with an Assigned( FVar ) guard, were everybody can agree on?

 

I can see much use of FAN in Delphi RTL, Spring4D and all many places all around, but at the same time everybody disagrees on its usefulness & better to avoid it,
thats strange ...


Where and why is it useful then, if not in situations where I want to check and mark the validity of a lazy Field or the like, for example by Assigned()?
I cannot think of much use-cases, where I would ever need this.

- If I use it in the case where I inject an object to a class, not by DI, but by method or property, then this would make sense to protect a Field by FAN, IMHO.

- In a use case where I purely manage a Field myself by Create/Destroy, it doesn't make much sense if there is no possibility of delayed access to it.

 

So maybe somebody has a clean example, to show where it makes sense?

 

Share this post


Link to post
18 minutes ago, Rollo62 said:

So maybe somebody has a clean example, to show where it makes sense?

If the variable is going out of scope, it doesn't make sense to nil it. If the variable is not going out of scope, then nil it.

 

I guess the question you might ask is why you would have a reference stay in scope after it is freed. That will depend on what is being done. For example, I do this if I have a lazy-loaded class field exposed as a property that is initialized in is getter. If there is something that invalidates the reference, it needs to be nilled so that it will not be freed again when the class is freed (double-freed), and so that it can be re-initialized the next time the property is read.

Share this post


Link to post

Sorry, I'm a little late to seeing this...

7 hours ago, Rollo62 said:

Yes, but from my experience, this helps to REDUCE the risk of AV's, in case of async processes, where you cannot safely cancel such async operation, because its not directly under your control.

I see it the other way - it can INCREASE the likelihood of an AV (or worse!).

 

The callback's Self pointer will be pointing at memory which the now-dead TMyClass object was occupying. It's undefined behavior for the callback to access that memory for ANY reason, period.  But let's forget that for a moment.

 

You nil the FMyVar member when freeing the TMyClass object, with the expectation that you can still access FMyVar later (which you can't).  If the memory that FMyVar was occupying  gets reused and overwritten before the callback is invoked, that memory might not be zeroed out anymore from the earlier nil.  And if it is not, then Assigned(FMyVar) will return True instead of False (if it doesn't just crash outright), and then you will try to call FMyVar.Add(...) and crash... or worse corrupt random memory trying to write to memory that it doesn't own.

  • Like 1

Share this post


Link to post

Ok, you both are right, but I still wonder why its used in so many places, if its that unnecessary.

The "reduce" was intended as fast fix, if you have no other choice to complete rework or repair anything in time, but you have to ship an update fast, used more or less like as a debugging tool.

There must be at least one real use-case, where FAN makes perfectly sense.

 

12 hours ago, Brandon Staggs said:

For example, I do this if I have a lazy-loaded class field exposed as a property that is initialized in is getter. If there is something that invalidates the reference, it needs to be nilled so that it will not be freed again when the class is freed (double-freed), and so that it can be re-initialized the next time the property is read.

Yes, I already mentioned this use-case, so is this the only one?

Why are there so many places using FAN during Create/Destroy, without any lazy injection?

I only can think of critical timing or race-condition protection somehow.

Share this post


Link to post
14 minutes ago, Rollo62 said:

Ok, you both are right, but I still wonder why its used in so many places, if its that unnecessary.

Because it is a plague :classic_biggrin:

 

14 minutes ago, Rollo62 said:

Yes, I already mentioned this use-case, so is this the only one?

 

15 minutes ago, Rollo62 said:

Yes, I already mentioned this use-case, so is this the only one?

Why are there so many places using FAN during Create/Destroy, without any lazy injection?

Reusing is the one scenario. Another scenario which you can see in very complex destructors which are part of some deep class hierarchy. It is not to prevent concurrency issues (because it can't prevent those), but it is used to prevent accessing already released fields during more complex cleanup. In such cases it must be paired with is Assigned checks. But this is rarely needed outside frameworks like VCL and FMX (and even there it is used in many places where it is not needed at all).

Share this post


Link to post
44 minutes ago, Dalija Prasnikar said:

Reusing is the one scenario. Another scenario which you can see in very complex destructors which are part of some deep class hierarchy. It is not to prevent concurrency issues (because it can't prevent those), but it is used to prevent accessing already released fields during more complex cleanup. In such cases it must be paired with is Assigned checks. But this is rarely needed outside frameworks like VCL and FMX (and even there it is used in many places where it is not needed at all).

Thanks, that sounds like I would never consider this in the first place. :classic_biggrin:

This is why I am asking for a simple, generic example to better understand why this would probably make sense.

Do you know a specific place in the VCL/FMX code, where it is used like that?

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×