Update to Undisposed.Fody

In my previous post I talked about Undisposed.Fody which has proven useful to me before in a live project. One problem I had however on using it was that I could see an undisposed object at a stage when I know it should have been disposed and flag this. The problem however was to know for sure who created the object as there could potentially be many branches in my code that could instantiate that dude.

To help myself I went and forked the gihub repo for Undisposed.Fody and added an option to dump the creation stacktrace on dumping undisposed objects. You can find my fork here. I have made a pull request and hope it will be added to the main repo.

Advertisements

Tracking undisposed items with Undisposed.Fody

I have recently had to do a little cleanup and ensure that there are no heavy objects that don’t get disposed. To do this I made use of my trusty friend Fody and the addin¬†Undisposed.Fody.

Undisposed.Fody is a Fody addin and a standalone application that helps to track down undisposed objects. Occasionally crashes or application hangs are caused by undisposed objects, especially if the objects references COM objects.

This tool injects some code in all classes that implement IDisposable. It registers the creation of such objects and dumps the undisposed objects together with object creation counter. This helps to set a breakpoint in the constructor and break on the n-th call, thus making it possible to see where the object got created (and not disposed later on)

https://github.com/ermshiperete/undisposed-fody

Below is a sample with comments that illustrates how this fody addin works.

Classes we will be tracking objects for disposal:


    public class  Sample2:Sample
    {
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                //dispose managed resources
            }
            //dispose unmanaged resources
            this.isDisposed = true;
        }
    }

    public class Sample : IDisposable
    {
        protected bool isDisposed;

        public void Dispose()
        {
            this.Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                //dispose managed resources
            }
            //dispose unmanaged resources
            this.isDisposed = true;
        }
    }

When using Fody (simply add Undisposed.Fody nuget reference) it will inject code on compilation. The sample classes above will be compile as follows (using Telerik JustDecompile to observer after build):


    public class Sample : IDisposable
    {
        protected bool isDisposed;

        public Sample()
        {
            DisposeTracker.Register(this);
        }

        public void Dispose()
        {
            DisposeTracker.Unregister(this);
            this.Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
            }
            this.isDisposed = true;
        }
    }

Next we set the DisposeTracker.OutputKind to Dump for verbositey and add a delegate to print to debug as the DisposeTracker.LogWriter Action. On dumping undisposed objects before initializing anything the dump is empty, after calling Test we can see that we have one undisposed object.


        static void Main(string[] args)
        {
            DisposeTracker.OutputKind = TrackerOutputKind.Dump;
            DisposeTracker.LogWriter = delegate(string s) { Debug.WriteLine(s); };
            DisposeTracker.DumpUndisposedObjects();
            Test();
            //at this point both variables created in test should be out of scope and disposed
            //Fody will show b - Sample2 as undisposed which will be a red flag, we can then go and fix it
            DisposeTracker.DumpUndisposedObjects();
        }

Output:

**** Undisposed Object Dump:
**** Undisposed Object Dump:
Fody.Undisposed_Recipe.Sample2: 1