views:

495

answers:

2

Is it possible to have a look at all .net objects which are collected upon calling GC.Collect()?

I need to see what objects are still in memory and not reclaimed, so I can find where reclaiming the objects should have done manual, but was forgotten by the programmer.
I don't want to call GC.Collect because someone somewhere forgot to dispose an object which blocks some handles.

+4  A: 

I've found the best way to do this is to use windbg and the SOS (son of strike) extension. It has a rather cryptic command line but it is very powerful. It has the capability to dump the heap and divide it by the GC generational heap. Once you get past the initial learning curve, it's very easy to track what objects are alive in what portion of the heap. Here are a few web sites with examples of using SOS

EDIT OP asked about the location of sos.dll. It is included with the install of the .Net Framework. It is located at

%WINDIR%\Microsoft.Net\Framework\V2.0.50727\sos.dll

But once you have windbg loaded you don't need the full path. Just us the .loadby method.

.loadby sos mscorwks.dll

It will look for the version of sos in the same directory as the current version of mscorwks (the CLR)

JaredPar
+1 for link to Tess Ferrandez's blog
Richard Szalay
@Richard, a very good blog indeed
JaredPar
Sounds great, now I just need to find somewhere to get SOS from...
Sam
@Sam, will edit post with location
JaredPar
I can't load sos.dll - does this not work with managed (mixed) c++?
Sam
It should work for any managed code as long as the CLR is loaded. Try using .load and the full path tho sos.dll.
JaredPar
I tried, I get: 'The call to LoadLibrary(C:\Windows\Microsoft.NET\Framework\v2.0.50727\SOS.DLL) failed, Win32 error 0n193'
Sam
CLR should be loaded. I break late in the program, and windbg tells me it has loaded a lot of .net-dlls, like: 'ModLoad: 71fb0000 72540000 C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll'
Sam
@Sam, are you on a 64 bit machine? If so use the framework64 version C:\Windows\Microsoft.NET\Framework64\v2.0.50727\SOS.DLL
JaredPar
Yes, I do, and this one loads! Still, commands like '!dumphead -stat' just print the msg 'No export dumphead found'.
Sam
Ouch, !dumpheaP, stupid me. Next error 'Failed to load data access DLL, 0x80004005' - grrr - am debugging at this issue for 3 days now, slowly it is getting to me...
Sam
@Sam, are you attaching with a 64 bit version of WinDbg? That's bitten me a few times
JaredPar
Yes, since I just downloaded and installed it - and the WinDbg window title says "WinDbg:6.11.0001.402 AMD64", too, so it should be the x64 version.
Sam
@Sam, are you debugging a .Net app that is targeting x86? If so you have to use the 32 bit version of WinDbg and sos.dll
JaredPar
Ah, yes, of course! Damn, thanks! I'll try to recompile the c++ as x64 (as soon as I find the compiler switch to achieve this), then try again - but tomorrow, I need a break now :) Thanks a lot so far!
Sam
@Sam, You're welcome. You could avoid a recompile by installing the x86 version of WinDbg (it will run in Wow64)
JaredPar
Good idea - using the x86 WinDbg it works. Pity, right now my test prog is leaking 27,000 handles, but the largest object count is 667, and thats System.String. So some collection contains my handles... but which one. *sigh* this will be tougher than expected.
Sam
@Sam look for the gcroot's. Can't remember which command off hand does this but there is a command that will give you the roots and it will lead you to the leak
JaredPar
+1  A: 

I use SciTech's Memory profiler. It's a bit complicated to use off the bat, but there are some good instructional videos. It'll let you look at which objects aren't disposed properly, in which generation they were collected. Couldn't debug memory leaks without it...

joshua.ewer