In the image below I reference an article you wrote back in 2008 titled Detecting hung Objects in Visual Forpro. In that article you show a fairly specific example of how to destroy objects so they con't hang. I'm trying to be sure I clearly understand how this might be caused.
In my image below, I show my understand in a block diagram and then in VFP code.
Is my example a correct understanding of what causes objects to hang?
If the property "vResult" (which is commented out in the DoSomething function) was used to pass back the "Y" object, I assume the EMPTY object along with its PK property would not hang when oX is released?
Thnaks for any comments

In your example, if your release oX
you will effectively clear and garbage collect that object instance and then when you release oY
it will cleanly release, because the reference of the object is released with it. Releasing the object instance explicitly in one place will not necessarily clear it everywhere.
The best rule of thumb for proper cleanup is that any dependent object that takes a reference to another object should be responsible for clearing that object. IOW, make sure you clear all child references before clearing the parent reference.
The most common scenario is what you describe but in reverse: You create a child object that has a reference to a parent object, and then the parent releases the second object that holds the child reference. At that point that second object becomes locked because it can't release the child object to the parent since it's still alive and active.
The way to fix that is to have a Dispose()
style method you call that cleans up the object, or implement a Destroy
handler that explicitly nulls out object references. The problem with Deploy
in VFP is that the rules on when that fires exactly is very nebulous. It only fires when all instances that are referenced are cleared, so for object cleanup this may not always fire when you think.
One piece of advice is: try to minimize the use of nested object references that are passed in and if you do excplicitly clear them.
As the post you reference points out circular refs are a pain in the butt to debug mainly because they are not a problem until there are a lot of them. So in typical dev scenarios you never know you have this problem and the debugging tools in VFP are inadequate to actually show you outstanding references. The only thing that does is DISPLAY MEMORY
and that also doesn't work with everything.
+++ Rick ---
I reviewed this with Zak to get an even better understanding, and helped me to correct the drawing (see below). The sample VFP code shown below reflects my understanding.
I added a Dispose() method as you suggested to null out the object that was created within the parent object. I'm assuming from your prior answer having object variables (setting to NULL) in the DESTROY() event is not a good practice.
Does this look more better
DEBUG
SUSPEND
loX = CREATEOBJECT("X")
loY = loX.DoSomething()
? VARTYPE(loX.loXY) && display O
loX.Dispose()
? VARTYPE(loX.loXY) && display X
**************************************
**************************************
DEFINE CLASS X AS CUSTOM
loXY = .null.
* add a method
********************
********************
FUNCTION DoSomething()
this.loXY = CREATEOBJECT("Empty")
RETURN this.loXY
ENDFUNC
********************
********************
FUNCTION Dispose()
this.loXY = .null.
RETURN .t.
ENDFUNC
********************
********************
ENDDEFINE
**************************************
**************************************
I think so - hard to tell with your diagram.
The idea is basically if you set a reference to another object in a parent object - always have a way to explicitly clean up that reference to make sure all dependencies are released. It's not always a problem but in some situations - especially when there are multiple chained dependencies that this becomes a problem.
It's safe to set an object reference that's a one way reference - the garbage collector can deal with that just fine. it's only when the links go both ways:
This sort of thing:
child-> Parent -> child
if child releases parent you'll have a hung reference. If parent releases child - no problem.
In the WebControl framework this sort of thing was very common where a parent form references each child control in a collection, and each child control has a reference back to the parent. In that case you to have each child have dispose method that clears the parent before getting released.
A good garbage collector can deal with stuff like that - .NET, JavaScript and most other modern engines can because they do a better job of reference counting, but Fox has problems with that sort of thing.
+++ Rick ---
