To use or not to use the Finalize method - to help memory management and GC

donnacha

Centurion
Joined
Feb 27, 2003
Messages
187
Hi folks,
this is a follow on from the eratic memory thread.

I am trying to confirm if using the Finalize method is a good thing or a bad thing. I have a lot of objects in my application and have a Dispose method and a Finalize method in each of them.
Now I go to great lenghts to ensure that the Dispose is called for these objects and also setting them to 'Nothing'
I have been reading the threads on MSDN

http://msdn.microsoft.com/msdnmag/issues/1100/GCI/TOC.ASP
http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/TOC.ASP
http://msdn.microsoft.com/library/en-us/dndotnet/html/dotnetgcbasics.asp

and I take from that that if I am calling my Dispose method that having a Finalize method will block the GC from releasing the memory associated witht he object.

Is this right or wrong.

:confused:
 
Finalize is called when an object is marked for garbage collection and becomes un-usable. It is used for cleaning up resources and things before the GC gets to it.

Dispose is called when you want to destroy the object and mark it for garbage collection. When you call Dispose on an object, the memory used by it will be freed and the GC will collect it when it can.

So yes... you should use the Finalize method for cleaning up objects used in the class. You can't call the Finalize method yourself (it's Protected), but unless you use GC.SuppressFinalize, the Finalize method will automatically be called when you dispose of an object.
 
A pattern I use is I implement IDisposable if a class has to release memory-intensive resources (db connections, file handles, etc.) when going out of scope. In the Dispose method, I examine a private level flag w/c tells whether resources have already been disposed or not. I also set the flag to True here so that it won't be executed again. After releasing the resources and setting the flag, I call GC.SuppressFinalize(Me <or this>) to signal to the GC that this instance's Finalize method doesn't have to be invoked.

Of course, client apps sometimes forget to call Dispose so in the Finalize sub, I also invoke Dispose. Here's a VB.NET boilerplate:

Visual Basic:
Public Class ResourceIntensiveClass
    Implements IDisposable
    Private m_blnAlreadyDisposed As Boolean
    '-Clients should call this method after using object.
    Public Sub Dispose() Implements IDisposable.Dispose
        '-Manually free up resources.
        FreeUpResources()
        '-Remove this instance from the finalizing queue since clean-up has been done.
        GC.SuppressFinalize(Me)
    End Sub
    Private Sub FreeUpResources()
        '-Release resources here; check first if resources haven't been freed already.
        If Not m_blnAlreadyDisposed Then
            '-Free up resources here...
            m_blnAlreadyDisposed = True
        End If
    End Sub
    Protected Overrides Sub Finalize()
        '-Free up resources in case Dispose wasn't invoked.
        FreeUpResources()
    End Sub
End Class

If you put your cleanup code in the Finalize method only, resources will not be immediately released since it is not guaranteed when the Finalize method will be invoked (although you can force GC, I'm sure you're aware that it's not recommended to do so).
 
Hi folks,
I agree with all ye say and have implemented it this way, but my question is arising from the MSDN articles I listed above. The following is an estract from one of them
----------------------------------------------------------------------
"How Finalization Affects Collection
When the garbage collector first encounters an object that is otherwise dead but still needs to be finalized it must abandon its attempt to reclaim the space for that object at that time. The object is instead added to a list of objects needing finalization and, furthermore, the collector must then ensure that all of the pointers within the object remain valid until finalization is complete. This is basically the same thing as saying that every object in need of finalization is like a temporary root object from the collector's perspective.

Once the collection is complete, the aptly named finalization thread will go through the list of objects needing finalization and invoke the finalizers. When this is done the objects once again become dead and will be naturally collected in the normal way.

Finalization and Performance
With this basic understanding of finalization we can already deduce some very important things:

First, objects that need finalization live longer than objects that do not. In fact, they can live a lot longer. For instance, suppose an object that is in gen2 needs to be finalized. Finalization will be scheduled but the object is still in gen2, so it will not be re-collected until the next gen2 collection happens. That could be a very long time indeed, and, in fact, if things are going well it will be a long time, because gen2 collections are costly and thus we want them to happen very infrequently. Older objects needing finalization might have to wait for dozens if not hundreds of gen0 collections before their space is reclaimed.

Second, objects that need finalization cause collateral damage. Since the internal object pointers must remain valid, not only will the objects directly needing finalization linger in memory but everything the object refers to, directly and indirectly, will also remain in memory. If a huge tree of objects was anchored by a single object that required finalization, then the entire tree would linger, potentially for a long time as we just discussed. It is therefore important to use finalizers sparingly and place them on objects that have as few internal object pointers as possible. In the tree example I just gave, you can easily avoid the problem by moving the resources in need of finalization to a separate object and keeping a reference to that object in the root of the tree. With that modest change only the one object (hopefully a nice small object) would linger and the finalization cost is minimized.

Finally, objects needing finalization create work for the finalizer thread. If your finalization process is a complex one, the one and only finalizer thread will be spending a lot of time performing those steps, which can cause a backlog of work and therefore cause more objects to linger waiting for finalization. Therefore, it is vitally important that finalizers do as little work as possible. Remember also that although all object pointers remain valid during finalization, it might be the case that those pointers lead to objects that have already been finalized and might therefore be less than useful. It is generally safest to avoid following object pointers in finalization code even though the pointers are valid. A safe, short finalization code path is the best."

----------------------------------------------------------------------

This seems to indiate that if your class has a 'Finalize' method that the memory will not be freed by the GC but will be put in the 'freachable' queue for later treatment and can thus live for a lot longer tha expected and thus still need to hold the memory.

Thus my question

"To use or not use a Finalize method."
 
Hi folks
those articles also talk about the "un-dead" objects that could be resurected from the GC (but not recommended, as you would assume).
 
Finalize is always used, The GC triggers a finalize before collecting, Finalize is Inherited from Object which is the base of everything so everything is finalized. The finalize cleans up things the GC won't for example, if you have a class that uses GDI DCs you shoould use FInalize to clear the DCs rather than causing amemory leak by not removing them. But you should use a Dispose method in this case but the dispose can work like this:
Visual Basic:
Public Class Cls
    Implements IDisposable

    Public Sub Dispose() Implements IDisposable.Dispose
       Me.Finalize()
    End Sub

    Protected Sub Finalize()
       'Release everything
    End Sub
End Class
Either method should work, its just how to use it
 
Last edited:
In my code snippet, note that the last call to the Dispose method is:

GC.SuppressFinalize(Me)

w/c tells the GC that this instance shouldn't be placed in the finalization queue (thus avoiding the undesirable effects stated in the article). So why still put code in the Finalize method? Because client apps are encouraged, but not required, to call your Dispose method before vars go out of scope. If Dispose isn't called, the Finalize call is the last chance for your cleanup code to execute. Yeah, it's evil but it's a lesser evil compared to doing nothing at all w/ the resources you're holding to.

If you look near the end of your third link, you'll find a brief discussion on the IDisposable interface w/c is "a great way to avoid, or at least reduce, finalization costs."
 
The ONLY code that should be located in a finalizer is code that frees unmanaged resources. Code located in Dispose() should first free managed resources, then free the same unmanaged resources as the finalizer. After all resources have been freed by Dispose(), GC.SupressFinalizer() should be called.

This is the only correct way of implementing IDisposable. If your class does not utilize unmanaged resources, a finalizer should not be used, as it only slows down the garbage collector, since instances of dependent objects need to held that much longer.
 
dereck: You say you should free all managed objects in the dispose event. I was under the impression that this was not needed. By freeing them I assume you mean setting all references to them to null/nothing. By doing this you are not actually freeing the memory until the GC runs, but regardless of whether you "free" them in the dispose event or not, when the GC runs it will look at the object graph and see that they are unreachable regardless of whether the references were deleted. If this is correct then I really see no point in freeing managed objects in the Dispose event (unless they use resources other than memory).

I am fairly inexperienced with .Net so I may have made some incorrect assumptions here, please correct me if I'm wrong.
 
By freeing them I assume you mean setting all references to them to null/nothing

No, he means disposing of managed resources that the class uses. One example is if you have a class that uses a Bitmap as a member variable then it'll need to be disposed of. This should be done in the classes dispose method.
 
Back
Top