Is it a bug in dotnet.framework? (about GC collection in 1.1 and 2

G

Guest

I tried a small program, found that some local objects can't be automatically
collected by GC. I tried both in 1.1 and 2.0, get the same result.
Below the program, just try it, you will found that the last 3 objects
didn't been released. Does anyone have some idear on it?


namespace TestMem
{
class Root
{
public Int32 m_ID;
public Root()
{
m_ID = this.GetHashCode();
}
~Root()
{
System.Threading.Monitor.Enter(ObjectMgr.m_list);
ObjectMgr.UnRegister(this);
System.Threading.Monitor.Exit(ObjectMgr.m_list);
}

}
class A : Root
{
}
class B : Root
{
}
class C : Root
{
}
class ObjectMgr
{
static int m_nRegisteredCnt = 0;
static int m_nUnRegCnt = 0;
static public System.Collections.ArrayList m_list = new
System.Collections.ArrayList();
static public void Register(Root obj)
{
System.Threading.Monitor.Enter(m_list);
m_nRegisteredCnt++;
m_list.Add(obj.m_ID);
System.Threading.Monitor.Exit(m_list);
}
static public void UnRegister(Root obj)
{
System.Threading.Monitor.Enter(m_list);
m_nUnRegCnt++;
m_list.Remove(obj.m_ID);
System.Threading.Monitor.Exit(m_list);
}
static public int GetCnt()
{
System.Threading.Monitor.Enter(m_list);
int nCnt = m_list.Count;
System.Threading.Monitor.Exit(m_list);
return nCnt;
}
static public void PrintUnreleasedObjects()
{
System.Threading.Monitor.Enter(m_list);
Console.WriteLine("Registered = {0}, Unregistered={1}",
m_nRegisteredCnt, m_nUnRegCnt);
int nTmp = 0;
foreach (int objID in m_list)
{
nTmp++;
Console.WriteLine("Objects in list, ID = {0}", objID);
if (nTmp >= 10)
break;
}
System.Threading.Monitor.Exit(m_list);
}
}
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 10000; i++)
{
A a;
B b;
C c;
a = new A();
b = new B();
c = new C();
a.m_ID = 3 * i;
b.m_ID = 3 * i+1;
c.m_ID = 3 * i+2;
ObjectMgr.Register(a);
ObjectMgr.Register(b);
ObjectMgr.Register(c);
if (i % 100 == 0)
{
Console.WriteLine("i={0}",i);
}
}//
while (ObjectMgr.GetCnt() > 0)
{
Console.WriteLine("There are {0} objects in list",
ObjectMgr.GetCnt());
ObjectMgr.PrintUnreleasedObjects();
System.Threading.Thread.Sleep(5000);
GC.Collect();
}
}
}
}
 
R

Richard Blewett [DevelopMentor]

Why would you expect any of the objects to be released?

They all have a root reference by being inserted in a *static* ArrayList. The GC.Collect() will discover that they are still reachable via the ObhectMgr.m_list. Also, in your finalizer there is no point in trying to unregister, as by the time you get there, the GC has already realized you have no root references.

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

I tried a small program, found that some local objects can't be automatically
collected by GC. I tried both in 1.1 and 2.0, get the same result.
Below the program, just try it, you will found that the last 3 objects
didn't been released. Does anyone have some idear on it?
 
G

Guest

In fact, the static ArrayList doesn't hold any object reference at all, it
only put the m_Id of the object into the ArrayList. So all the object should
be release by collector.
 
J

Jon Skeet [C# MVP]

Yingkun Hu said:
I tried a small program, found that some local objects can't be automatically
collected by GC. I tried both in 1.1 and 2.0, get the same result.
Below the program, just try it, you will found that the last 3 objects
didn't been released. Does anyone have some idear on it?

Does that mean the program doesn't terminate for you? It does for me.

If you're running it in the debugger, that would explain things - local
variables aren't eligible for garbage collection until the method
terminates when running in the debugger,

A couple of points on the code, by the way:

1) Finalizers are horrible - get rid of them wherever possible, and
implement IDisposable wherever you *have* to have them.

2) Use lock() rather than calling Monitor.Enter/Exit explicitly.
 
J

Jon Skeet [C# MVP]

Sriram Krishnan said:
Curious - why do you say this?

1) It's easier to read
2) You end up with the required try/finally (which the OP's code misses
out) automatically.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top