The following code has a memoryleak.
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
AssemblyResolveMemoryTest assemblyResolveMemoryTest = new AssemblyResolveMemoryTest();
}
}
}
class AssemblyResolveMemoryTest
{
private byte[] _allocateMemory;
public AssemblyResolveMemoryTest()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
//memory is not released anymore
_allocateMemory = new byte[300000000];
}
System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
return null;
}
}
It seems the AssemblyResolve event cause the memory leak.
What is the reason for this?
Do i need to remove the eventhandler explicitly in this case?
If yes, where is the right place to remove this eventhandler? Implement IDisposable or use Try/Finally?
Yes, the event will cause a memory leak. It’s because AppDomain.CurrentDomain.AssemblyResolve is static, so its life doesn’t end until the program ends. So, it will have to keep a reference to all event handlers that have been registered (+=) to it so that they remain in memory when an event occurs which will result in the handlers being called.
I would suggest that you implement IDisposable in class AssemblyResolveMemoryTest and get it to -= the event.
Then within the for loop, add a using statement which will cause the dispose to be called.
You could store the assemblyResolveMemoryTest instances in a list and write a second loop that goes round calling Dispose on them before your program exists. There’s not much point in this though because when your program exists, everything will be dispose and the ‘leaked memory’ will be freed.
So, in reality, if you do want these event handlers to remain and be in use for the life of your program, then this isn’t actually a memory leak and is memory usage your program needs to function as you want it to.
I guess the buffer isn’t something you have in a real program, and you’re just using it to demonstrate the problem. Perhaps, if you’ve got memory referenced by your a real assemblyResolveMemoryTest equivalent object in production code, you could try and restructure your program so that the event handler for AssemblyResolve isn’t part of an object that holds onto other memory that’s not relevant to the handling of the event.
You could use a static method as the event handler, so that no member objects of the class will stay around in memory as you won’t actually need to create an instance of the class in the first place.