Random collection of notes, personal tips, and general things.

Bits & Bytes

  • Follow Us on Twitter!
  • LinkedIn

Finalizers and the Garbage Collector

To review the threads for a .net application, start up ntsd and point it at a .net executable.

 Get started in the usual manner;

.symfix (to set the symbol store file path to local to the exe)

.reload to reload modules & symbols

g to start the application. 

Once the app is running, break into the debugger with Ctrl-C.

 

Load the sos debugger extensions from the same location that the clr dll is executing from;

.loadby sos clr

And now we're ready.

Review the threads for the app using the !threads debugger extension.  For some reason the first extension will always throw an exception.  Try again & below you can see one thread for the simple testing console application and the dedicated Finalizer thread responsible for executing any Finalizers.

Any object that has a finalizer defined will be put on the finalizer queue even if that object is live & not ready for collection by the garbage collector.

To review the finalizer queue & whats sitting on it, use the !FinalizeQueue extension

You can see at the moment, there's nothing in the Finalizer Queue for any of the generations (0 finalizable objects) and the F-Reachable Queue is also empty.  The F-Reachable queue is the queue where objects that the GC has determined are dead and need to have their finalizer invoked are moved to.  The F-Reachable Queue is the queue that the Finalizer thread works its way through sequentially invoking the finalizers for each object in this queue.

The test console app that is running has a simple class with a Finalizer declared

    public class File : IDisposable
    {
        private bool isDisposed;
        public string Path { get; set; }

        private void Dispose(bool isDisposing)
        {
            // cleanup resources
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        ~File()
        {
            Dispose(false);   
        }
    }

A new instance of a File object is being created in the console app and then breaking into the debugger before any other processing occurs.

       static void Main(string[] args)
        {
            Console.WriteLine("Enter any key to put finalizer object onto heap");
            var command = Console.ReadLine();

            var file = new File();

 

 The FinalizeQueue is showing that there are now 8 generation 0 objects in the FinalizerQueue - and the Statistics for all finalizable objects is showing the ConsoleApp.File object.

Add comment

Loading