Surely you’ve been through those situations where a user or a tester reports a situation that you can’t reproduce in your development environment. Even if your environment is properly set up, some bugs (such as a Heisenbug) can be very difficult to reproduce. Sometimes you even have to diagnose the program in the testing/production environment! Those are the times you wish you had a dump of the process state when the bug occurred. Heck, you’ve even read recently that Visual Studio 2010 allows you to open memory dumps, so you don’t even have to deal with tools like windbg, cdb or ntsd!
Wouldn’t it be great if you could instruct your program to generate a minidump when it stumbles upon a catastrophic failure?
Microsoft supplies a Debug Help Library which among other features, allows you to write these memory dumps. The code below is a .NET wrapper to this particular feature, which allows you to easily create a memory dump.
Note however that the target assembly must be compiled against .NET 4.0, otherwise visual studio will only be able to do native debugging.
Having the code to write a dump, let’s create an error situation, to trigger the memory dump creation. Let’s just create a small program that try to make a division by zero.
Running this program will throw an obvious DivideByZeroException, which will be caught by the try catch block and will be handled by generating a memory dump.
Let’s go through the process of opening this memory dump and opening it inside Visual Studio 2010. When you open a dump file in VS, it will present a Summary page with some data about the system where the dump was generated, the loaded modules and the exception information.
Note that this summary has a panel on the right that allows you to start debugging. We’ll press the “Debug with Mixed” action to start debugging.
Starting the debug of a memory dump will start debugger with the exception that triggered the dump, thus you’ll get the following exception dialog:
After you press the “Break” button, you’ll be shown the source code as shown below. Note the tooltip with the watch expression “$exception” (you can use this expression in the immediate or the watch window whenever you want to check the value of the thrown exception, assuming somewhere up in the stack you are running code inside a catch block) where you can see the divide by zero exception that triggered the memory dump.
You can also see the call stack navigate through it to the Main method where the exception was caught. All the local and global variables are available for inspection in the “Locals” and “Watch” tool windows. You can use this to help in your bug diagnosis.
The approach explained above automatically writes a memory dump when such an error occurs, however there are times when you are required to do post-mortem debugging in applications that don’t automatically do this memory dumping for you. In such situations you have to resort to other approaches of generating memory dumps.
One of the most common approaches is using the debugger windbg to achieve this. Let’s see how we could have generated a similar memory dump for this application. If we comment the try catch block and leave only the division by zero code in our application, it will throw the exception and immediately close the application. Using windbg to capture such an exception and create a memory dump of it is as simple as opening windbg, selecting the executable we’ll be running:
This will start the application and break immediately (this behaviour is useful if we want to set any breakpoints in our code). We’ll order the application to continue by entering the command “g” (you could also select “Go” from the “Debug” menu).
This will execute until the division by zero throws the exception below. When this happens, we’ll order windbg to produce our memory dump with the command ‘.dump /mf “C:\dump.dmp”’.
After this your memory dump is produced in the indicated path and you can open it in visual studio as we’ve previously done.
Post-mortem is a valuable resource to debug some complex situations. This kind of debugging is now supported by Visual Studio, making it a lot easier, even though for some trickier situations you’ll still need to resort to the power of native debuggers and extensions like SOS.
4 comentários:
Nice blog... is it possible to configure ADPLUS to gather a memory dump only once for an expecific type of exception, say OutOfMemory?
Hi Nestor, I have never used adplus for that specific situation, but I know it can be done. You have to create a configuration file for adplus. Here's a couple of useful links: http://blogs.msdn.com/b/carloc/archive/2007/10/08/ok-now-how-do-i-capture-my-dump.aspx ; http://msdn.microsoft.com/en-us/library/ff537972%28v=VS.85%29.aspx ; http://msdn.microsoft.com/en-us/library/ff554689%28v=VS.85%29.aspx . Pay special attention to the last link as it is a sample configuration to achieve exactly what you need. But maybe you should read the other two links first. Good luck with it!
Hello. Did you share DumpLib anywhere?
Hi Sergey. I did not share DumpLib anywhere, but I believe all the code used in this blog post (including DumpLib) is included either in the 2 blocks of code or screenshots included in the post.
Best regards
Enviar um comentário