C# hierarchical data structure and .NET garbage collection ?
-
Assuming I've defined a hierarchy of #whatever that allows nesting an arbitrary number of levels : then, I delete a reference to a top-level #whatever instance which contains #n levels deep of #n other #whatever instances: Can I assume that the #whatever instance now-without-a-reference, and all its sub-levels of references/instances, will be garbage collected ? Or, is it on me to recursively remove child references ? Of course, it is on me to handle references in the code to sub-elements that are "outside" the parent/ancestor inheritance chain. Is there a specific 'Dispose technique that can be used here ? Note: I've deliberately phrased the hypothetical here in an abstract way, to avoid talking about what a specific Control, like the WinForms TreeView, might implement internally. thanks, Bill
«When I consider my brief span of life, swallowed up in an eternity before and after, the little space I fill, and even can see, engulfed in the infinite immensity of spaces of which I am ignorant, and which know me not, I am frightened, and am astonished at being here rather than there; for there is no reason why here rather than there, now rather than then.» Blaise Pascal
-
Assuming I've defined a hierarchy of #whatever that allows nesting an arbitrary number of levels : then, I delete a reference to a top-level #whatever instance which contains #n levels deep of #n other #whatever instances: Can I assume that the #whatever instance now-without-a-reference, and all its sub-levels of references/instances, will be garbage collected ? Or, is it on me to recursively remove child references ? Of course, it is on me to handle references in the code to sub-elements that are "outside" the parent/ancestor inheritance chain. Is there a specific 'Dispose technique that can be used here ? Note: I've deliberately phrased the hypothetical here in an abstract way, to avoid talking about what a specific Control, like the WinForms TreeView, might implement internally. thanks, Bill
«When I consider my brief span of life, swallowed up in an eternity before and after, the little space I fill, and even can see, engulfed in the infinite immensity of spaces of which I am ignorant, and which know me not, I am frightened, and am astonished at being here rather than there; for there is no reason why here rather than there, now rather than then.» Blaise Pascal
Hi Bill, 1. an object is dead and collectable as soon as you no longer have a reachable reference to it (reachables are inside other obects that are reachable, stacks, static variables, ...). When a number of objects have internal references to each other but no outside references are alive, then all of those objects are dead/collectable. 2. exactly when they get garbage collected is more complex, it depends on the size, the generation number, when your GC runs, etc. However one normally should not care about this, that is the GC's job. 3. when your objects have a Dispose() method (necessary when they may hold pointers to unmanaged system resources), then for each of them the Dispose() method will be called eventually by the GC. In this case it is advisable to call their Dispose() explicitly so the system resources get released ASAP. Note: providing a Dispose() method will somewhat postpone the GC freeing their memory, so providing a Dispose() on huge objects is a bad idea! 4. when your Application terminates neither of those mechanisms will work for you; instead Windows itself will reclaim all memory and all system resources your program was using (unless...), so you can't safely implement wanted side effects in your Dispose() method as your program might terminate before Dispose() gets called by the GC! Hope this helps and is sufficiently clear and accurate. :)
Luc Pattyn [My Articles] Nil Volentibus Arduum
-
Hi Bill, 1. an object is dead and collectable as soon as you no longer have a reachable reference to it (reachables are inside other obects that are reachable, stacks, static variables, ...). When a number of objects have internal references to each other but no outside references are alive, then all of those objects are dead/collectable. 2. exactly when they get garbage collected is more complex, it depends on the size, the generation number, when your GC runs, etc. However one normally should not care about this, that is the GC's job. 3. when your objects have a Dispose() method (necessary when they may hold pointers to unmanaged system resources), then for each of them the Dispose() method will be called eventually by the GC. In this case it is advisable to call their Dispose() explicitly so the system resources get released ASAP. Note: providing a Dispose() method will somewhat postpone the GC freeing their memory, so providing a Dispose() on huge objects is a bad idea! 4. when your Application terminates neither of those mechanisms will work for you; instead Windows itself will reclaim all memory and all system resources your program was using (unless...), so you can't safely implement wanted side effects in your Dispose() method as your program might terminate before Dispose() gets called by the GC! Hope this helps and is sufficiently clear and accurate. :)
Luc Pattyn [My Articles] Nil Volentibus Arduum
Thanks, Luc, that is very clear, very helpful. cheers, Bill
«When I consider my brief span of life, swallowed up in an eternity before and after, the little space I fill, and even can see, engulfed in the infinite immensity of spaces of which I am ignorant, and which know me not, I am frightened, and am astonished at being here rather than there; for there is no reason why here rather than there, now rather than then.» Blaise Pascal
-
Hi Bill, 1. an object is dead and collectable as soon as you no longer have a reachable reference to it (reachables are inside other obects that are reachable, stacks, static variables, ...). When a number of objects have internal references to each other but no outside references are alive, then all of those objects are dead/collectable. 2. exactly when they get garbage collected is more complex, it depends on the size, the generation number, when your GC runs, etc. However one normally should not care about this, that is the GC's job. 3. when your objects have a Dispose() method (necessary when they may hold pointers to unmanaged system resources), then for each of them the Dispose() method will be called eventually by the GC. In this case it is advisable to call their Dispose() explicitly so the system resources get released ASAP. Note: providing a Dispose() method will somewhat postpone the GC freeing their memory, so providing a Dispose() on huge objects is a bad idea! 4. when your Application terminates neither of those mechanisms will work for you; instead Windows itself will reclaim all memory and all system resources your program was using (unless...), so you can't safely implement wanted side effects in your Dispose() method as your program might terminate before Dispose() gets called by the GC! Hope this helps and is sufficiently clear and accurate. :)
Luc Pattyn [My Articles] Nil Volentibus Arduum
-
Hi Luc It seems you have mixed finalizers and IDisposable.Dispose() in your reply. :) The garbage collector will never call Dispose. It will call the finalizer if one is present.
You're right, thanks. :)
Luc Pattyn [My Articles] Nil Volentibus Arduum
-
Hi Luc It seems you have mixed finalizers and IDisposable.Dispose() in your reply. :) The garbage collector will never call Dispose. It will call the finalizer if one is present.
Thanks. I must admit this had me doubting myself and scratching my head.
This space for rent
-
Thanks. I must admit this had me doubting myself and scratching my head.
This space for rent
If I were wiser, would I doubt you, or Marc, or Richard, or Luc, or OG, and others here, speak from profound knowledge+experience ? I doubt it. I scratch my head often, but the right kind of doubt does not come. :wtf: cheers, Bill
«When I consider my brief span of life, swallowed up in an eternity before and after, the little space I fill, and even can see, engulfed in the infinite immensity of spaces of which I am ignorant, and which know me not, I am frightened, and am astonished at being here rather than there; for there is no reason why here rather than there, now rather than then.» Blaise Pascal
-
If I were wiser, would I doubt you, or Marc, or Richard, or Luc, or OG, and others here, speak from profound knowledge+experience ? I doubt it. I scratch my head often, but the right kind of doubt does not come. :wtf: cheers, Bill
«When I consider my brief span of life, swallowed up in an eternity before and after, the little space I fill, and even can see, engulfed in the infinite immensity of spaces of which I am ignorant, and which know me not, I am frightened, and am astonished at being here rather than there; for there is no reason why here rather than there, now rather than then.» Blaise Pascal
Bill, you should doubt everything I say. Especially this. ;)
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay... AntiTwitter: @DalekDave is now a follower!
-
Assuming I've defined a hierarchy of #whatever that allows nesting an arbitrary number of levels : then, I delete a reference to a top-level #whatever instance which contains #n levels deep of #n other #whatever instances: Can I assume that the #whatever instance now-without-a-reference, and all its sub-levels of references/instances, will be garbage collected ? Or, is it on me to recursively remove child references ? Of course, it is on me to handle references in the code to sub-elements that are "outside" the parent/ancestor inheritance chain. Is there a specific 'Dispose technique that can be used here ? Note: I've deliberately phrased the hypothetical here in an abstract way, to avoid talking about what a specific Control, like the WinForms TreeView, might implement internally. thanks, Bill
«When I consider my brief span of life, swallowed up in an eternity before and after, the little space I fill, and even can see, engulfed in the infinite immensity of spaces of which I am ignorant, and which know me not, I am frightened, and am astonished at being here rather than there; for there is no reason why here rather than there, now rather than then.» Blaise Pascal
I found a really great description of dotNet garbage collection in CLR via C#[^]. That book turned me around about automatic garbage collection. At least half a dozen times I said to myself something like "Hey, that's smart! I would never have thought of that if I were to manage the heap myself!" I used to be sceptical about automatic GC - now I am sceptical to those who claim they can do better themselves. It is like an optimizing compiler vs. assembly code: The optimizer will discover a lot of tricks that the assembler coder wont. The only problem remaining now is that you believe that you have removed the last reference to that 1 Gbyte data structure, and you are waiting for ages for it to go away, forgetting that you still have a reference to it in some static struct holding, say, user preferences. (Maybe you needed that reference e.g. during initialization, but never after that.) This is similar to, say, forgetting to close files. (There was a similar situation in old style Unix file systems, where anyone with read access to a file could create another link to it, preventing it from being deleted: When the creator/owner removed his last link, he lost control over it; your 'secret' link might be the only access path to the file, keeping it alive, keeping disk space from being released. But the owner is still the same, so he will have to pay for the disk storage! - I think remedies for handling this was introduced many years ago, but in the first years of Unix, it was a real problem.)