1

In my application I am using lots of com objects.

I am releasing all com object, which I declared but my application is triggering some other application which is also using some com object and that application creating memory leak.

Triggering part activates from a loop so I have a chance to release all com objects in every iteration. I wanted to know is there any way so that I can release all com objects which were used by another application.

I have used following code for releasing com object.

if (feature != null) 
{ 
    while (Marshal.ReleaseComObject(feature) > 0) 
    { }
 }

I understand that GC maintain a table which hold all entry related to all reference object but how GC behave if some other application creating heap inside my application space.

Bhaskar Singh
  • 410
  • 6
  • 15

1 Answers1

2

You're manually implementing what amounts to the same thing as FinalReleaseComObject. If you're going to do this, I would think you would want to just go ahead and use the built-in FinalReleaseComObject method, since semantically it represents exactly what you're doing in your loop, and since it's a built-in part of the framework that's likely to get bug-fixing love from Microsoft if there's something wrong with it, and because using it adheres to DRY.

From Microsoft's MSDN page on FinalReleaseComObject (emphasis is mine):

When the reference count on the COM object becomes 0, the COM object is usually freed, although this depends on the COM object's implementation and is beyond the control of the runtime. However, the RCW can still exist, waiting to be garbage-collected.

However, this article on CodeProject, as well Microsoft's Patterns and Practices, suggests that you not use FinalReleaseComObject, and that instead you make darn sure that you call ReleaseComObject in the opposite order of what you instantiated the objects in.

In other words, have one and only one ReleaseComObject paired up with each assignment. Judicious use of try/finally is probably a good idea, to guarantee that the release occurs for each assignment.

Do this, and your RCW reference count for each COM object will naturally drop to 0 as you "unwind" your COM object graph, then if your COM object isn't ill-behaved it should be freed.

Note what the CodeProject article says about being sure to release COM objects returned from method calls. If you just ignore those return values, it doesn't mean they don't exist. You'll have references to them sitting around waiting for multiple generations of garbage collection. So you need to be sure to call ReleaseComObject on those, as well:

Marshal.ReleaseComObject( myCom.ProcessError (5) ); //Release returned object
Marshal.ReleaseComObject( myCom );

Using FinalReleaseComObject seems to be a little more like throwing a Hail Mary and praying for the best. It's kind of like you're saying "Hey, I didn't really pay attention when I was spinning up this object, but please try really hard to make it go away for me."

Craig Tullis
  • 9,939
  • 2
  • 21
  • 21
  • I am using ReleaseComObject in my finally block and i am freeing multiple object in finally block. I am not using FinalReleaseComObject because this is not suggested (http://stackoverflow.com/questions/3937181/when-to-use-releasecomobject-vs-finalreleasecomobject)" . But my problem is still unanswered because i want to release all other comObject which is not part of my code base. I am sure that they have completed there work, but they are bothering me because they are called in a loop and loop goes millions of time. – Bhaskar Singh Aug 06 '14 at 16:35
  • But `while (Marshal.ReleaseComObject(feature) > 0){}` essentially **IS** `FinallyReleaseComObject`, and my point was that the official docs (and my experience) are clear that you need to pair up instantiation and release 1-for-1, not instantiate lots and lots of COM objects then try to release them all in a single `finally` block. – Craig Tullis Aug 06 '14 at 21:27
  • The only COM objects you can explicitly release are ones you have instantiated in your code, and that includes COM objects that are return values of COM functions you call. Even if you ignore those return values, they're still floating around hooked up to RCW's waiting for GC. If you use a COM object which creates another COM object but doesn't pass you a reference to the downstream object, I'm pretty sure you'll have to trust the COM object you have to free those resources. Or maybe you could shell out a whole independent process for whatever this task is, then kill the process on completion. – Craig Tullis Aug 06 '14 at 21:29
  • Well i am releasing them in one 'finally' block. I also observing a behavior that if i am disabling the code which is triggering every thing working fine. – Bhaskar Singh Aug 06 '14 at 21:33
  • i also think in same way but complication is i have no control over other resources. My DLL is part of a big software. i am doing lots of insert, update and delete operations in my code which triggering lots of events in that software and there are lots of other DLL working based on those event. And Because application space is shared for all dll they are causing problem. I even dont know which dll is creating memory leak, i am only guessing that there is some AutoUpdator which are creating problem. But i am not sure which one and even if i know i cant fix them as those are not part of my code – Bhaskar Singh Aug 06 '14 at 21:49
  • Are you sure that the methods you're calling on your COM objects aren't returning COM objects themselves? If so, you need to release those returned COM objects. You cannot just ignore them. If you're making millions of calls to COM methods which return COM objects, and you just ignore the return values, you are pumping millions of COM object references into garbage collection where you have no guarantee as to when the finalizers will be called on all those RCW's. Thus, `Marshal.ReleaseComObject( myCom.ProcessError (5) ); //Release returned object`, where `ProcessError(5) returns a COM object. – Craig Tullis Aug 07 '14 at 03:38