I wasn't totally sure where to go for help with this so I figured I'd try stackoverflow since it usually has answers for about 90% of all my programming related questions.
In a nutshell I've got an open source .NET application that's leaking memory. It might not be a true memory leak in the sense that, when the application closes I suspect the memory is reclaimed, but while it's running it constantly allocates more memory without freeing it. Eventually, a System.OutOfMemoryException
is thrown.
To debug the problem I followed the steps recommended in this article, and produced the following graph, where red is the .NET/CLR Memory "#Bytes in all Heaps" and green is the Process "Private Bytes" with windows' Performance Monitor tool (Note the green line has been uniformly scaled down to appear closer to the red line, since only the shapes of the lines matter to me): Performance Monitor Output.
I took the image as evidence of a managed memory leak and followed up with windows' Debug Diagnostic Tool to try and locate the source of the leak (as mentioned in the article). However the report I got back from Debug Diagnostic Tool is very peculiar.
Basically every attempt to collect a "Full UserDump" which I tried to do every 5 seconds while the application was running, was thwarted by the fact that the garbage collector was always in the middle of a garbage collection cycle at the time, causing Debug Diagnostic Tool to output an error, and preventing it from gathering any useful .NET memory related info.
Now I'm stuck, I know I have a managed memory leak, but I don't know how to narrow down where it is. I'm also confused about how the garbage collector was always in the middle of a collection cycle, it makes me wonder if the garbage collection thread was somehow blocked, preventing it from freeing memory and/or exiting the garbage collection cycle.
There are some sections of the Performance Monitor Graph where the allocated .NET memory goes down a bit, so the garbage collector wasn't stuck forever, but it must have been for most of the time, otherwise Debug Diagnostic should have been able to do a UserDump.
A couple of questions:
Is it possible for the garbage collector in a .NET application to get stuck while trying to free some memory, perhaps from some poorly coded destructor/finalizer or something?
What strategy can I use to continue narrowing down the source of the problem?