Clean up of memory leak in unmanaged code

R

Ragnar Agustsson

Hi all

I have been wandering about the best way to sandbox memory leaks in 3rd
party libraries when using them from the .Net framework.

I have a 3rd party library, written in C++, that leaks a lot of memory
but I still had to use it.

1.
After using DLLImport and seeing the memory leak I tried to load and
unload the library using the kernel's LoadLibrary and FreeLibrary. That
did not work as the leaked memory was not reclamed, not surprising as
my main .Net app's process was still alive.

2.
Then I read about AppDomain, that sounded pretty cool as it can unload
assemblies. So my hope was that the GC would be intelligent enough to
see the leaked memory and do a cleanup at that time. So I wrapped the
leaking C++ DLL in a C# assembly and loaded it, saw it leak memory,
then I unloaded the assembly and and saw it being unloaded. But the
memory was still missing...

3. Then I did the only thing I new would work, I wrote an out of
process COM object that I kill off with Marshal.ReleaseComObject to get
my memory back. I have thought about putting the logic into the COM
object itself, i.e. it would perform harakiri when consuming too much
memory or just with a certain interval or inactivity timeout. But this
approach does seem like a bit of a fudge to me...

So my question is:
Is there anyone out there who has found an elegant way of cleaning up
unmanaged memory leak using .Net?

Best regards,
Ragnar Agustsson
 
K

KWienhold

I don't think you will have much luck with the GC here, since these
problems arise with unmanaged code and that is exactly it, it's
unmanaged, so the GC won't deal with it.
Unfortunately I don't have a more elegant solution either, I usually
also use Marshal.ReleaseComObject when a memory leak occurs in
unmanaged libraries.
Depending on the situation you might be able to allocate the memory
yourself and free it when you are done, but I don't really consider
that to be more elegant or even more useful (unless you need to keep
the reference to the unmanaged object).

Sincerely,
Kevin Wienhold
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

I think that your third option is the best way to go, you need to host the
leaking code in a different process (unfortunately using an AppDomain did
not worked, not "external enough").
 
N

Nicholas Paldino [.NET/C# MVP]

Ragnar,

#3 is your best bet, to have the COM object run out of process, and then
have the process die when you are done with it.

You might get some help from hosting the COM object in COM+, as you
could have the app recycle should it consume/occupy more than a certain
amount of memory. Then, you just have to access it from .NET, and you
should be good.

Of course, you left out option #4, which is to get the source of the
component or a fix for the component in question. =)

Hope this helps.
 
N

Nicholas Paldino [.NET/C# MVP]

Kevin,

Your recommendation to use Marshal.ReleaseComObject for when a memory
leak occurs in unmanaged libraries is a bad one. There is no basis to do
this. If there is a memory leak in the unmanaged library, then that is not
going to be solved by the COM object being disposed of. If the COM object
is not managing the unmanaged memory correctly, then releasing it will not
do anything.

Rather, you are not managing the lifetime of the COM object correctly,
and are calling ReleaseComObject to account for that. Granted, you have to
do it at some point, but you need to know at WHAT point to do it.

Hope this helps.
 
W

Willy Denoyette [MVP]

Ragnar Agustsson said:
Hi all

I have been wandering about the best way to sandbox memory leaks in 3rd
party libraries when using them from the .Net framework.

I have a 3rd party library, written in C++, that leaks a lot of memory
but I still had to use it.

1.
After using DLLImport and seeing the memory leak I tried to load and
unload the library using the kernel's LoadLibrary and FreeLibrary. That
did not work as the leaked memory was not reclamed, not surprising as
my main .Net app's process was still alive.

2.
Then I read about AppDomain, that sounded pretty cool as it can unload
assemblies. So my hope was that the GC would be intelligent enough to
see the leaked memory and do a cleanup at that time. So I wrapped the
leaking C++ DLL in a C# assembly and loaded it, saw it leak memory,
then I unloaded the assembly and and saw it being unloaded. But the
memory was still missing...

3. Then I did the only thing I new would work, I wrote an out of
process COM object that I kill off with Marshal.ReleaseComObject to get
my memory back. I have thought about putting the logic into the COM
object itself, i.e. it would perform harakiri when consuming too much
memory or just with a certain interval or inactivity timeout. But this
approach does seem like a bit of a fudge to me...

So my question is:
Is there anyone out there who has found an elegant way of cleaning up
unmanaged memory leak using .Net?

Best regards,
Ragnar Agustsson


I second Nicholas advise about option 4, a piece of code that leaks memory is buggy code,
let the 3rd party fix it.

Willy.
 
R

Ragnar Agustsson

Hi Nicholas

Acually Kevin's reccommendation works if the COM object is an out of
process object, i.e. COM server. Because it lives in a different
process and thus the memory is reclaimed when it is disposed of.

Best regards,
Ragnar
Kevin,

Your recommendation to use Marshal.ReleaseComObject for when a memory
leak occurs in unmanaged libraries is a bad one. There is no basis to do
this. If there is a memory leak in the unmanaged library, then that is not
going to be solved by the COM object being disposed of. If the COM object
is not managing the unmanaged memory correctly, then releasing it will not
do anything.

Rather, you are not managing the lifetime of the COM object correctly,
and are calling ReleaseComObject to account for that. Granted, you have to
do it at some point, but you need to know at WHAT point to do it.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

KWienhold said:
I don't think you will have much luck with the GC here, since these
problems arise with unmanaged code and that is exactly it, it's
unmanaged, so the GC won't deal with it.
Unfortunately I don't have a more elegant solution either, I usually
also use Marshal.ReleaseComObject when a memory leak occurs in
unmanaged libraries.
Depending on the situation you might be able to allocate the memory
yourself and free it when you are done, but I don't really consider
that to be more elegant or even more useful (unless you need to keep
the reference to the unmanaged object).

Sincerely,
Kevin Wienhold
 
R

Ragnar Agustsson

I wish I had option 4, it would be the best one of course.

Thank you all for your replies, it confirmed my belief.

Best regards,
Ragnar
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top