[Mono-bugs] [Bug 384723] New: Dictionary prevents GC

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Tue Apr 29 07:51:18 EDT 2008


https://bugzilla.novell.com/show_bug.cgi?id=384723


           Summary: Dictionary prevents GC
           Product: Mono: Class Libraries
           Version: 1.9.0
          Platform: Other
        OS/Version: Mac OS X 10.4
            Status: NEW
          Severity: Major
          Priority: P5 - None
         Component: System
        AssignedTo: mono-bugs at lists.ximian.com
        ReportedBy: jesjones at mindspring.com
         QAContact: mono-bugs at lists.ximian.com
          Found By: ---


Unlike System.Collections.Generic.List System.Collections.Generic.Dictionary
does not zero out elements when they are removed or when the collection is
cleared. Instead Dictionary merely marks the corresponding slot as unused. 

This is pretty bad because it means the default conservative garbage collector
in mono 1.9 will think that there is still a reference to the cleared objects
and prevent them from being collected. They will only be collected when the
slot is reused.

Here's a test case:

// compile with: gmcs -out:app.exe -target:exe Dictionary.cs
using System;
using System.Collections.Generic;
using System.Threading;

// With mono 1.9 I get the following output:
//    removed an item from the dict, but delta is 0
//    cleared the dict, but delta is 0

internal class Item
{        
    ~Item()
    {
        --ms_instanceCount;
    }

    public Item()
    {
        ++ms_instanceCount;
    }

    public static int Count
    {
        get {return ms_instanceCount;}
    }

    private static int ms_instanceCount;
}

internal class Program
{    
    private static void Main()
    {
        TestList();        
        TestDict();

        ForceCollect();
        MyAssert(Item.Count == 0, "finished but count is " + Item.Count);

        if (!ms_failed)
            Console.WriteLine("passed");
    }

    private static void TestList()
    {        
        List<Item> l = new List<Item>();

        int initial = Item.Count;
        l.Add(new Item());
        l.Add(new Item());
        l.Add(new Item());
        ForceCollect();
        MyAssert(Item.Count == initial + 3, "added 3 items to a list, but delta
is " + (Item.Count - initial));

        initial = Item.Count;
        l.RemoveAt(0);
        ForceCollect();
        MyAssert(Item.Count == initial - 1, "removed an item from the list, but
delta is " + (Item.Count - initial));

        initial = Item.Count;
        l.Clear();
        ForceCollect();
        MyAssert(Item.Count == initial - 2, "cleared the list, but delta is " +
(Item.Count - initial));
    }

    private static void TestDict()
    {        
        Dictionary<int, Item> d = new Dictionary<int, Item>();

        int initial = Item.Count;
        d.Add(1, new Item());
        d.Add(2, new Item());
        d.Add(3, new Item());
        ForceCollect();
        MyAssert(Item.Count == initial + 3, "added 3 items to a dict, but delta
is " + (Item.Count - initial));

        initial = Item.Count;
        d.Remove(2);
        ForceCollect();
        MyAssert(Item.Count == initial - 1, "removed an item from the dict, but
delta is " + (Item.Count - initial));

        initial = Item.Count;
        d.Clear();
        ForceCollect();
        MyAssert(Item.Count == initial - 2, "cleared the dict, but delta is " +
(Item.Count - initial));
    }

    private static void ForceCollect()
    {
        System.GC.Collect();
        Thread.Sleep(200);        // note that we need to sleep to allow the
finalizer thread to kick in
   }

    private static void MyAssert(bool p, string s)
    {
        if (!p)
        {
            Console.WriteLine(s);
            ms_failed = true;
        }
    }

    private static bool ms_failed;
}


-- 
Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.


More information about the mono-bugs mailing list