3
votes

After a few minutes of work the managed memory contains a lot of unreferenced objects of the type that was created by implemeting interface from interop assembly. GC.Collect does not remove objects from memory.

It looks that .NET creates COM callable wrapper for the .NET objects and the wrapper somehow holds the references to the object. But how to investigate this?

Investigation:

0:016> !dumpheap -stat
Loading the heap objects into our cache.
total 905,554 objects
Statistics:
        MT    Count    TotalSize       Change Class Name
...
0x05127ac0      796        9,552          796 Application.GenericListener
...
Total 905,554 objects, Total size: 77,354,192

Types are defined as follows:

// C# code:
public class GenericListener: OurEventListener, IDisposable { ... }
// GenericListener does NOT have finalizer
public abstract class OurEventListener : EventListener { ... }

//Interop assembly:
[Guid("...")]
[TypeLibType(256)]
[InterfaceType(1)]
public interface IListener { ... }

Types are used as follows:

var listener = new GenericListener();
ourComObject.Subscribe(listener);
...
ourComObject.Unsubscribe(listener);
listener.Dispose();

Objects:

0:016> !dumpheap -mt 0x05127ac0
Loading the heap objects into our cache.
 Address       MT     Size
027a11d4 05127ac0       12    2 Application.GenericListener
0326d354 05127ac0       12    2 Application.GenericListener
09c5812c 05127ac0       12    2 Application.GenericListener
09c83000 05127ac0       12    2 Application.GenericListener
...

Objects are roots:

0:016> !gcroot 027a11d4
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 0 OSThread 1444
Scan Thread 2 OSThread b40
Scan Thread 7 OSThread 1630
Scan Thread 8 OSThread a8
Scan Thread 13 OSThread 1328
DOMAIN(005F2E30):HANDLE(RefCnt):182d48:Root:  027a11d4(Application.GenericListener)

Any ideas?

Update: add how the listener is used.

1
There a reason you are not disposing of the object yourself? You have little control over the garbage collector and any control you do have comes at a performance cost. You have posted very little of the code, I am going to guest, the gc is unable to collect it the resources because it was dispose the code.Security Hound
Are you using CLR hosting? I mean do you load your managed code inside an unmanaged process?Aliostad
@Ramhound Dispose is called for all these objects. Anyway, finalizer is not defined in GenericListener so GC should just remove it when the object is unreferenced. But it does not.Alex Netkachov
@Aliostad GenericListener is passed to the COM object, but it is in the same process.Alex Netkachov

1 Answers

0
votes

Is this a COM object that you are using from C#? Check that you have called FinalReleaseComObject or ReleaseCOMObject as required if so, to release the RCW.