I know the answer (it's 42)

A blog on coding, .NET, .NET Compact Framework and life in general....

January, 2010

Posts
  • I know the answer (it's 42)

    Back to Basics: Memory leaks in managed systems

    • 1 Comments
    Kolkata Trip 2009

    Someone contacted me over my blog about his managed application where the working set goes on increasing and ultimately leads to out of memory. In the email at one point he states that he is using .NET and hence there should surely be no leaks. I have also talked with other folks in the past where they think likewise.

    However, this is not really true. To get to the bottom of this first we need to understand what the the GC does. Do read up http://blogs.msdn.com/abhinaba/archive/2009/01/20/back-to-basics-why-use-garbage-collection.aspx.

    In summary GC keeps track of object usage and collects/removes those that are no longer referenced/used by any other objects. It ensures that it doesn’t leave dangling pointers. You can find how it does this at http://blogs.msdn.com/abhinaba/archive/2009/01/25/back-to-basic-series-on-dynamic-memory-management.aspx

    However, there is some catch to the statement above. The GC can only remove objects that are not in use. Unfortunately it’s easy to get into a situation where your code can result in objects never being completely de-referenced.

    Example 1: Event Handling (discussed in more detail here).

    Consider the following code

    EventSink sink = new EventSink();
    EventSource src = new EventSource();
    
    src.SomeEvent += sink.EventHandler;
    src.DoWork();
    
    sink = null;
    // Force collection
    GC.Collect();
    GC.WaitForPendingFinalizers();

    In this example at the point where we are forcing a GC there is no reference to sink (explicitly via sink = null ), however, even then sink will not be collected. The reason is that sink is being used as an event handler and hence src is holding an reference to sink (so that it can callback into sink.EventHandler once the src.SomeEvent is fired) and stopping it from getting collected

    Example 2: Mutating objects in collection (discussed here)

    There can be even more involved cases. Around 2 years back I saw an issue where objects were being placed inside a Dictionary and later retrieved, used and discarded. Now retrieval was done using the object key. The flow was something like

    1. Create Object and put it in a Dictionary
    2. Later get object using object key
    3. Call some functions on the object
    4. Again get the object by key and remove it

    Now the object was not immutable and in using the object in step 3 some fields of that object got modified and the same field was used for calculating the objects hash code (used in overloaded GetHashCode). This meant the Remove call in step 4 didn’t find the object and it remained inside the dictionary. Can you guess why changing a field of an object that is used in GetHashCode fails it from being retrieved from the dictionary? Check out http://blogs.msdn.com/abhinaba/archive/2007/10/18/mutable-objects-and-hashcode.aspx to know why this happens.

    There are many more examples where this can happen.

    So we can conclude that memory leaks is common in managed memory as well but it typically happens a bit differently where some references are not cleared as they should’ve been and the GC finds these objects referenced by others and does not collect them.

  • I know the answer (it's 42)

    .NETCF: The mini Y2K

    • 3 Comments
    Kolkata Trip 2009

    I am sure most people haven’t yet forgotten the Y2K problem. This year our team faced a mini Y2K, but don’t worry we anticipated it and all is well.

    If you head over to NETCF Wikipedia page you’d notice the NETCF versions look as follows

    <MajorVersion>.<MinorVersion>.<Year><DayofYear>.<Rev>

    A sample version number is

    3.5.7283.0

    This represents .NETCF version 3.5 build on the 283rd day of 2007. I guess by now you can guess the problem. We use a single digit to represent the year. By that nomenclature, the version of the build churned out today would be 3.5.0001.0 which is lower than the one generated the year before and would fail to install.

    These numbers are automatically generated by scripts on the server that churns out daily builds. The numbering system was invented a long time ago in early 2000 and no one bothered to fix it. We anticipated that it’s going to fail as we move into the new decade and have updated it to now have 2 digits for the year (and yes we know it will break again in the future, but hopefully that’s too far out to care right now).

    Happy new Year.

Page 1 of 1 (2 items)