Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling memory leaks caused by an external assembly

I need to use an external assembly that I cannot modify. Suppose that I use a class from that assembly like so:

using (ExternalWidget widget = new ExternalWidget())
{
    widget.DoSomething();
}

Each time I call this code, it leaks unmanaged memory. ExternalWidget implements IDisposable and I have wrapped it in a using statement, but ExternalWidget does not clean up its unmanaged resources.

Since I do not have access to the ExternalWidget code, I cannot fix this issue the right way. Is there any other way that I can free up the memory resources used by ExternalWidget?

like image 459
markyd13 Avatar asked Oct 25 '12 13:10

markyd13


People also ask

What is the main cause of memory leaks?

DEFINITION A memory leak is the gradual deterioration of system performance that occurs over time as the result of the fragmentation of a computer's RAM due to poorly designed or programmed applications that fail to free up memory segments when they are no longer needed.

What will be the effect if there is a memory leak in an operating system?

A memory leak reduces the performance of the computer by reducing the amount of available memory. Eventually, in the worst case, too much of the available memory may become allocated and all or part of the system or device stops working correctly, the application fails, or the system slows down vastly due to thrashing.


1 Answers

If it is a true unmanaged memory leak and you can't change the code, then there's little that you can do. The framework can't pick up on that, nor can it clean up that code.

The approach in this case would be isolation of that component. It means there's going to be a lot of overhead in accessing it, but there's nothing else you can do.

You can't run the code in another application domain, because the unmanaged code has no concept of the application domain.

That leaves the process level. I'd recommend creating a service contract in WCF that mimics the calls to the ExternalWidget along with a Shutdown method.

Then, you would create an EXE which would expose this contract (with a session, so you can hold onto the ExternalWidget instance, unless each call is stateless) through named pipe bindings.

As a parameter to the EXE, it would take a unique identifier (use a Guid) and use that as part of setting up the endpoint for the WCF service.

Then, you would make the calls, and when you're done with that instance of ExternalWidget, call Shutdown; the EXE would know to stop waiting and then the process will exit, and the operating system will reclaim the memory.

Of course, there's a huge amount of overhead here, so if you find you're making a lot of calls and don't need a new process for each set of calls, you can expand the idea into a service which counts the calls and then recycles the process (the service will still have to shell out, or it will run out of resources) when needed.

Note that if this turns out to be a managed memory issue, then you can always spin up a new application domain, run your code there (marshaling the results back and forth as needed) and then release the application domain.

like image 141
casperOne Avatar answered Sep 30 '22 20:09

casperOne