I'm using a COM object from .NET using interop. The object basically fetch data from socket and fire some events for .NET layer to process. However, after a while, the COM object stops firing events which revealed later to be because it's collected by GC.
The structure of source code is similar to this one below:
static void Main(string[] args)
{
MyEventGen gen = new MyEventGen();
WeakReference wr = new WeakReference(gen);
gen.ReceiveDataArray +=
new _IMyEventGenEvents_ReceiveDataArrayEventHandler(gen_ReceiveDataArray);
while (true)
{
Thread.Sleep(1000);
Console.WriteLine(wr.IsAlive);
}
}
static void gen_ReceiveDataArray(ref Array indices, ref Array values)
{
// do nothing
}
What I know so far:
From what I understand, object gen
shouldn't be garbage-collected in any way. Since the object is still active in the Main
scope. But the result so far shows that the object was collected by GC.
The object is only garbage-collected when built as Release and run without debugging. Running the Debug builds / running both modes under debugger are fine.
The program will print the first "False" precisely after the first Gen #0 Collection.
By accessing the object in the while
loop, e.g. Console.WriteLine(gen.ToString())
, prevent it from being GC'd!
By adding another static field of Program
class to keep its reference also prevent it from GC'd.
Trying with different load of data, I found that GC only collects the object when Private Bytes reach over the threshold of ~ 3X MBs.
Checking with CLRProfiler, mentioned object was GC'd as suspected.
Have I missed some important .NET GC's concepts? Is it possible to obtain the reason for object being GC'd? Is this, possibly, a known GC bug?
I'm using VS 2008 + .NET 3.5 SP1. Appreciate your thoughts. Thanks!
An object is eligible to be garbage collected if its reference variable is lost from the program during execution. Sometimes they are also called unreachable objects. What is reference of an object? The new operator dynamically allocates memory for an object and returns a reference to it.
Objective-C 2.0 adds garbage collection to the language as a replacement to the traditional retain / release reference counting scheme. Garbage collection is automatic object memory management.
The main objective of Garbage Collection is to free heap memory by destroying the objects that don't contain a reference. When there are no references to an object, it is assumed to be dead and no longer needed. So the memory occupied by the object can be reclaimed.
The best example of garbage collector is Daemon thread that is always running in the background. So, the main objective of Garbage Collector in java is to free up heap memory by destroying unreachable objects that are not referenced by any reference variable.
No need to use a COM object to reproduce this. Consider the following:
public class MyEventGen
{
public event Action ReceiveDataArray;
}
class Program
{
public static void Main()
{
var gen = new MyEventGen();
var wr = new WeakReference(gen);
// this is the last time we access the
// gen instance in this scope so after this line it
// is eligible for garbage collection
gen.ReceiveDataArray += new Action(gen_ReceiveDataArray);
// run the collector
GC.Collect();
while (true)
{
Thread.Sleep(1000);
Console.WriteLine(wr.IsAlive);
}
}
static void gen_ReceiveDataArray()
{
}
}
Run it in Release mode and it will exhibit the same behavior. The gen
object falls out of scope and is garbage collected because there is nothing to keep it alive during the execution of the loop.
Neither gen
nor wr
remain active in the Main scope during the execution of your while
loop.
You enclosed the first three lines in braces which puts those variables in a child scope that is exited before your while
loop begins.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With