views:

348

answers:

2

A legacy c++ applications with sometimes notorious memory leak issues has to be called from a .Net server based windows application. .Net garbage collection times are not determinable and sometime the c++ object are destroyed or not destroyed "on time" producing unpredictable results and generally crashing the c# web app. What is the best way to push the c++ objects onto the garbage collection stack as frequently as possible, but not so often as to remove the .Net reference to the COM object. Keep in mind that the COM objects can spawn sub-objects so the .Net reference count of the COM objects can change with just a function call and not necessarily an instantiation.

As the memory leaks occur and the COM objects are not cleaned up, performance degrades until it is so slow that IIS trips on itself a few times and then crashes. Restarting IIS fixes the issue until the next time. Periodic restarts help, but a busy day can cause this during the business day.

I had to resolve this using .Net 1.1 a couple of years ago. Wondering if someone else had my solution or a better one. This is NOT ASP.NET. It is a .Net dll.

The final result was not completely satisfactory and the web server crashes every few months.

+1  A: 

You ask "What is the best way to push the c++ objects onto the garbage collection stack as frequently as possible", but c++ objects are never garbage-collected. Maybe look at it this way...

You have a process that instantiates a bunch of c++ objects. Some of those c++ objects implement COM objects, and their lifetime is therefore managed via AddRef/Release. Some of those COM objects are imported into the .NET world, and are wrapped with an RCW (runtime-callable wrapper). Only the RCW is a .NET object and goes in the garbage-collected heap.

Without any intervention from you, the RCW will eventually be GC'd and when that happens it will do a Release against its underlying COM object. If you want to Release the COM object immediately, without waiting for GC, you can call...

System.Runtime.InteropServices.Marshal.ReleaseComObject

... or even FinalReleaseComObject if you're sure it's what you want.

To get back to your question: you want to know how to delete the c++ objects without releasing the .NET reference to your COM object. Since the c++ objects don't exist in the .NET heap, there's no way to achieve this directly. You could expose a method from your COM object that deletes all its c++ objects, and simply call that from your .NET code. But I guess if it was possible for your COM object to identify all the leaked c++ objects you'd be doing that already.

Hopefully I've explained why there's no way to achieve what you suggest in your question, but there are plenty of tools around to help you find and fix your memory leaks. I suggest using a tool such as LeakDiag (search StackOverflow for it) to find out where your c++ code is leaking memory.

The pragmatic solution, if you're using IIS6 or higher, is to configure application pool recycling. You can tweak the numbers so that processes are killed and restarted before they've ever leaked enough memory to be problematic, and it normally works in such a way that users don't notice any downtime.

Martin
A: 

Create a COM+ application and put the COM classes you use inside that application. This way all COM objects are instantiated in a separate process. You can periodically release all COM objects and just restart the COM+ application process.

sharptooth
Keeping the COM objects in a separate process is an interesting idea. I'm not sure if it's possible.
ssorrrell
That's how COM+ works. You take your in-process COM server and ask COM+ to create a "COM+ application" which is really just an out-of-process COM+ server with the same functionality. And out-of-process means that all objects are in a separate process.
sharptooth