Why "Finalize method should not reference any other objects"?
Asked Answered
C

2

7

I have been pondering why it is recommended that we should not release managed resources inside finalize. If you see the code example at http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx , and search for string "Dispose(bool disposing) executes in two distinct scenarios" and read that comment, you will understand what I mean.

Only possibility I can think of is that it probably has something to do with the fact that it is not possible to predict when finalizer will get called. Does anyone know the right answer ?

thanks, mishal

Chaechaeronea answered 22/4, 2010 at 6:26 Comment(0)
C
11

If you're referencing another object from the finalizer, you don't know if that object has already been finalized - and how it will behave if it is finalized. (I don't know whether any current CLR runs multiple finalizer threads, but another scary possibility is that it's in the process of being finalized when your finalizer runs.)

All you should need to do in a finalizer is release unmanaged resources that you own directly. If you're referencing other managed types which own resources, let them do their job in their finalizers.

Contemporize answered 22/4, 2010 at 6:32 Comment(12)
But if my object (which is currently getting finalized) is holding a reference to the other managed object, I think CLR ensures that the referenced object is alive at this stage. (im just guessing by the concept of garbage collection, that as long asan object is referenced it will not get cleaned up)Chaechaeronea
But if my object (which is currently getting finalized) is holding a reference to the other managed object, I think CLR ensures that the referenced object is alive at this stage. (im just guessing by the concept of garbage collection, that as long asan object is referenced it will not get cleaned up). So it would be a CLR bug i think if the referenced object is already finalized before the parent object is finalized.Chaechaeronea
As long as an object is reachable, it won't be cleaned up. If your object is being finalized, then it isn't reachable, and any references it's holding aren't either (and thus don't count).Henhouse
@mishal153: The garbage collector discerns three categories of objects: -1- Objects which are reachable by other live root objects; -2- Objects which are registered for finalization, or are reachable by those that are, but are not reachable by any other live root objects; -3- Those which aren't reachable at all. Objects in the second category get added to an "immediate finalization" queue, which is a rooted object, but will no longer be considered "finalizable". The fact that an object is reachable from a finalizable object will prevent it from being swept away, but will not prevent it...Fanatic
...from being finalized. Note that if a finalizable object holds references to objects that together occupy 100MB of memory, the system won't be able to sweep away any of those objects until after the finalizer has run.Fanatic
@Fanatic What's preventing the object reachable from finalizable object from being swept away? If it can be finalized, then it should be "removable" too, no?Karame
@MuditJain: No - because the finalizer may resurrect it.Contemporize
@JonSkeet: Finalizer may resurrect a finalized object? For what? So runtime can reuse the memory space for another object of same type created in future? (Thanks for the answer, saw your video on Pluralsight recently).Karame
@MuditJain: No, so that the object can become alive again. Basically, if the finalizer copies this to some root (e.g. a static field) then it can't be collected.Contemporize
@JonSkeet: I read this to understand what you and supercat are talking about dotnettricks.com/learn/netframework/… . But why would finalizer copy a deleted object to some static root?Karame
@MuditJain: It doesn't happen often, but the system has to account for the possibility that it would happen.Contemporize
@MuditJain: When an object is identified as eligible for immediate finalization, an strong reference is created to it. This in turn creates a strong reference to all objects that are reachable from it, prior to performing the GC sweep.Fanatic
S
2

I think you've pretty much hit the nail on the head. If you look at the wording in the Object.Finalize documentation, it says: See the IDisposable interface for a complementary and more controllable means of disposing resources. "Complementary" meaning, "another way to do it," and controllable being..exactly what you said.

Edit: And what Jon Skeet said. The notion of multiple finalizer threads has ensured I will either not be sleeping, or having very bad dreams tonight.

Soutine answered 22/4, 2010 at 6:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.