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

mishal153
  • 1,498
  • 3
  • 26
  • 37

2 Answers2

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.

Cameron
  • 96,106
  • 25
  • 196
  • 225
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    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) – mishal153 Apr 22 '10 at 06:37
  • 1
    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. – mishal153 Apr 22 '10 at 06:43
  • 6
    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). – cHao Apr 22 '10 at 06:45
  • 2
    @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... – supercat Feb 20 '11 at 21:36
  • 1
    ...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. – supercat Feb 20 '11 at 21:37
  • @supercat 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? – Mudit Jain Mar 28 '18 at 13:13
  • @MuditJain: No - because the finalizer may resurrect it. – Jon Skeet Mar 28 '18 at 13:18
  • @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). – Mudit Jain Mar 28 '18 at 13:45
  • @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. – Jon Skeet Mar 28 '18 at 13:46
  • @JonSkeet: I read this to understand what you and supercat are talking about http://www.dotnettricks.com/learn/netframework/net-garbage-collection-and-finalization-queue . But why would finalizer copy a deleted object to some static root? – Mudit Jain Mar 28 '18 at 14:15
  • @MuditJain: It doesn't happen often, but the system has to account for the *possibility* that it would happen. – Jon Skeet Mar 28 '18 at 14:16
  • @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. – supercat Mar 29 '18 at 14:22
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.

Marc Bollinger
  • 3,109
  • 2
  • 27
  • 32