Memory issues are amongst the worst one to solve because pointing precisely the source is often difficult and painful. Memory leaks are not an exception, especially with real-world application: most of the time, programmers start to worry about it when the application outputs some “out of memory” errors. At this moment, you have to find which one, among thousands of functions and many more allocated blocks, causes the application to leak and eventually to crash.
Let’s summarize what you really need when you have a memory leak (in addition to a way to reproduce the issue):
- You want to find which object(s) are leaking
- You want to know why they are leaking: is there some static reference to it, or maybe they are not freed?
The process described today deals with the first one, which is often the most difficult.
- a normal termination (you reach the end of the main function)
- a call to ExitProcess, potentially located anywhere in your code
- an exception walking up all through the call stack of its thread, making the process die.
Sometimes bug happens before you have the chance to attach a debugger to the faulting process. Most of the time it’s because it is launched by another process (a service, the compiler used to create a Xml serializer of a .NET software, a batch script, etc.) and you don’t have the time to get the command line with ProcessExplorer. And even if you can get it, a process may expect some context coming from its parent. And obviously, sometimes you don’t have a clue about how a process is launched, all you know is that it crashes and you need to see what’s inside before it do so.
After a few tryout to pause the process (Process Explorer is your friend) before it crashes, or some tentative to slow down your computer so you have the time to attach a debugger, you’re starting to get frustrated. Hopefully I have some solutions for you.
Since a few weeks (months maybe?) the only way to download the marvelous “Debugging Tools for WIndows” package is something quite difficult : first you have to go to the Microsoft dedicated website, then get the whole Windows SDK package (just a web download starter…) and find which option to install to finally get the Windbg executable. Beyond those annoying steps, Microsoft added another difficulty: the description of each option in the installer is not descriptive at all. And again, publish only an installer for a product that is have been designed to avoid any kind of installation (think about your production server where you really want to use that debugger…) is a little bit weird, isnt’it?
Following the advise of a good friend, I choose to reveal the almost-hidden checkbox and especially give the zipped file of the x86 and x64 version.
Maybe this post will be the shorter ever of this blog, but I have to write something about it. Microsoft offer two version of their Debugging Tools: a x86 version, and a x64 version. Which one do you have to use?
On 32-bit OS, the answer is really simple: you don’t have the choice but to use the x86 version, as the OS will not be able to start a 64-bit executable. End of the decision tree :)
On 64-bits OS, it depends on what you want to debug. Unless you need to dig deep inside the Wow64 layers (and I never had to do that personally, but speaking about it makes me curious about what I can found), just use the x86 version to debug a 32-bits executable, and the x64 version to debug a 64-bits executable. If you mess up with this simple rule, you may encounter serious difficulties to get CLR information through SOS (well, it’s basically not possible as far as I know), have wrong data about common memory structure that Windbg can display, and maybe be unable to load your favorite extension.
Maybe you thought when you read this title: “well it’s kind of easy, I just have to attach any debugger to my running service“. And you’re definitely right.
But sometimes you have to debug the very beginning of your service (just after the “Start” control), or even before, when the main() function has just started. Or you’re experiencing a bug that happens only with a specific user, or only in a context of a Windows service (could be environment variables, registry keys, etc.). Hopefully, with a few tricks, you can easily setup a debugger that will attach to a process just after its creation.