Rollo62 550 Posted 21 hours ago 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
Brandon Staggs 337 Posted 21 hours ago 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
Remy Lebeau 1506 Posted 21 hours ago 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. 1 Share this post Link to post
Rollo62 550 Posted 9 hours ago 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
Dalija Prasnikar 1439 Posted 8 hours ago 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 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
Rollo62 550 Posted 7 hours ago 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. 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
David Heffernan 2380 Posted 3 hours ago I get all the arguments that using FAN in a destructor is pointless, because how can you using that reference beyond the destructor. And I understand the argument for using it in a reference for an object that exists optionally, and can be destroyed outside of the destructor. What I don't get is what the downsides of using FAN are. What are the drawbacks? Share this post Link to post
Dalija Prasnikar 1439 Posted 3 hours ago 3 hours ago, Rollo62 said: Do you know a specific place in the VCL/FMX code, where it is used like that? No. I remember seeing such code, but I cannot tell you the exact place. It is hard to find them because in most places RTL, VCL, and FMX use FreeAndNil when it is not needed at all or for lazy initialized/reusable variables. Share this post Link to post
Dalija Prasnikar 1439 Posted 3 hours ago Just now, David Heffernan said: What I don't get is what the downsides of using FAN are. What are the drawbacks? For me it is about code intent. FreeAndNil implies reusable variables and more complex instance lifetime. Free implies the opposite. Share this post Link to post
Anders Melander 1899 Posted 2 hours ago 4 minutes ago, Dalija Prasnikar said: For me it is about code intent. FreeAndNil implies reusable variables and more complex instance lifetime. Free implies the opposite. Instead of FreeAndNil implying a certain pattern I think it would be better to explicitly state, in a comment, when and why a certain behavior is expected. The projects I'm working on right now has something in the neighborhood of 200 calls to FreeAndNil in it. All except two are there to catch stale pointers; FreeAndNil gives us a nice AV that we can easily debug. Free would most likely give us a sporadic random error somewhere else. The two remaining cases are in a framework where we need a container var to be nilled before the object is destroyed. I won't go into why it's necessary; I'm sure you know the pattern. Anyway, for these two cases, the comments in the code clearly document why the FreeAndNil pattern is necessary. This is an old project and the introduction of FreeAndNil, where it makes sense of course, has helped us catch and eliminate countless bugs. Before I took over as the lead the code was littered with hundreds of empty try..except blocks simply because they had given up on trying to find the cause of the exceptions. 1 Share this post Link to post
Dalija Prasnikar 1439 Posted 1 hour ago 42 minutes ago, Anders Melander said: Instead of FreeAndNil implying a certain pattern I think it would be better to explicitly state, in a comment, when and why a certain behavior is expected. Of course, but plenty of code doesn't have that. Share this post Link to post
Rollo62 550 Posted 1 hour ago @Anders Melander I found an older case of yours, here at DevExpress. https://supportcenter.devexpress.com/ticket/details/t812550/an-av-occurs-if-the-spell-checker-whose-usethreadedload-property-is-set-to-true-reloads Which speaks against FreeAndNil too. Share this post Link to post