| crashrpt |
A crash reporting system for Windows applications

# Using Crash Minidump

You can open minidump files generated by CrashRpt in Visual Studio or in WinDbg.

This page covers the following topics:

- About Crash Minidump
- Opening Minidump in Visual Studio
- Opening Minidump in WinDbg

## About Crash Minidump

The minidump (DMP file) contains various information about the state of the application when the error occurred. The minidump is usually created with the help of the DbgHelp DLL's MiniDumpWriteDump() function.

The crash minidump file may contain:

- general system information
- call stack and local variables for each execution thread
- values of global variables
- the list of loaded and unloaded modules

The actual content of the minidump depends on the minidump type you pass as CR_INSTALL_INFO::uMiniDumpType member.

In order to recover the stack trace from the crash minidump, you need the debugging symbols (program database, PDB) generated by the linker for important modules of your application.

## Opening Minidump in Visual Studio

In order to illustrate how to open a minidump file, I will use the minidump file created for CrashRptTest.exe demo application that is distributed with CrashRpt archive. I use the following steps to create such minidump:

- I download CrashRpt archive to some directory. Then I unzip my archive to D:\Projects\CrashRpt\dmptest folder.
- In the top-level directory, I open CrashRpt_vs2005.sln file (because I have Visual Studio 2005 installed) and compile CrashRpt in Release configuration as described in Compiling CrashRpt.
- Then I go to the bin directory. I see that the Visual Studio created several EXE, DLL and PDB files for me. Then I close Visual Studio window.
- Next I save the binary files, debugging information and source code to some directory as described in Preparing to Software Release. I just copy the bin directory to D:\Projects\CrashRptSaved directory and (because I use SVN to store my code) make SVN checkout to D:\Projects\CrashRptSaved\src directory.
- Next I go to the bin directory again and run the CrashRptTest.exe. When dialog appears, I click the "Crash" button. When Error Report dialog appears, I click the "What does this error report contains?" link. Then in the Error Report Details dialog, I click the "Export..." button to export the error report files as a ZIP archive. I export my error report to D:\Projects\ErrorReports directory.
- And then I unzip the error report archive, which contains crashdump.dmp file and several other files.

Finally, I have the following directry structure:

- D:\
  - Projects
    - CrashRpt
      - dmptest
    - CrashRptSaved
      - bin
      - src
    - ErrorReports

Now, when you have crashdump.dmp file, you can open it in Visual Studio. In order to open crash minidump file, double-click its file name. Alternatively, if you have several versions of Visual Studio installed (for example a commercial one and an Express edition) right-click the filename and in the context menu select Open With and then choose what Visual Studio version to use.

A new Visual Studio window will appear. In the Visual Studio window, you should be able to see the solution called crashdump and having single project node called crashdump.dmp.

Solution Explorer: crashdump

In the Visual Studio window, open menu Debug->Start debugging (or press F5) to load the minidump data. When minidump is loaded, you will see the dialog containing information about the exception, such as exception address, module name, exception code and its textual description (see the figure below). Press the 'Break' button to continue.

Unhandled Exception Message

In the Output window, you should be able to see the log of minidump loading progress. If you do not see the Output window, open menu View and click the Output menu item. In the Output window, you can see what symbol files are loaded for each module.

Output Window

Now look at the Modules window. If you do not see such window, open menu Debug->Windows and select the Modules menu item. Click the Symbol Status column header twice to sort modules by symbol load status in descending order. Now you should be able to see that symbols are loaded for CrashRptTest.exe and CrashRpt.dll modules.

Modules: Symbols load status for each module

As the debug symbols seem to be loaded successfully for main modules of the application, in the code window you should be able to see the place in your source code where the exception occurred. I see that the crash occurred in file CrashRpt.cpp at line 706 inside of crEmulateCrash() function because of assigning a null pointer variable with the value 0.

You can see values of local variables by moving the mouse cursor over the variable name. The value (if known) is displayed in a tooltip window. Not all variable's values can be recovered, this depends on the minidump type you use and on other factors, such as code optimizations.

Line of the code where exception occurred

If the reason of the crash is clear, you can even want to edit the source code right in place to fix the problem. But I wouldn't recommend to do this, because the code you are browsing is a 'snapshot', not a working copy. And there is a bug in Visual Studio 2005 that makes a filename lowercase when you save the changes.

In order to better understand the reason of the crash, I would like to know what C++ class or function called the crEmulateCrash() function and for what purpose. I can do this with the help of the Call stack window (see the figure below). If the Call stack window is hidden, open menu Debug->Windows and select the 'Call Stack' menu item.

Call Stack

Each line (also called a stack frame) of the stack trace contains the name of module the code belongs to, the name of symbol (function or class), offset from beginning of symbol code, source file and line number. Moving down the stack, I see that crEmulateCrash() was called by the CMainDlg::DoCrash() class method, which, in turn was called by the CMainDlg::OnOK() method as the result of button click.

Typically, the program has several execution threads. You can switch between threads using the Threads tab and browse the stack for each thread. I see that there are two threads in the application: __tmainCRTStartup and CrashThread. The exception occured in the main thread, the second thread didn't crash.

Threads Window

Finally, when you have finished with analyzing minidump data, close the Visual Studio window. If Visual Studio offers you to save the solution, click the 'No' button.

## Troubleshooting

The case described above is the easiest one, because Visual Studio located all binaries, PDB files and source files automatically. But in general, there may be some problems with reading minidumps, when Visual Studio can't locate such files.

In order to locate matching binaries, PDB files and source code files, Visual Studio uses the absolute paths embedded into the PDB file at the time of compilation and linking. So, when you do not delete/move/modify the files you used to build the solution, Visual Studio can locate them automatically. But, if you delete/move or modify those files, Visual Studio won't be able to locate them. In order to illustrate such case, I will remove the entire D:\Projects\CrashRpt\dmptest folder that contained CrashRpt source code I used in compilation, resulting binaries and PDB files. Then I open the minidump again and see the message 'No symbols are loaded for any stack frame. The source code can't be displayed' (see the figure below).

No Symbols Loaded

Also look at the Modules window - symbol status for CrashRptTest.exe and CrashRpt.dll modules shows that there were no matching binaries found. In order to fix this, you should specify symbol search path manually. Open Tools->Options->Debugging->Symbols and enter the path to the directory where your PDB files are located (see the figure below for example).

Where to load symbols from

Now reload the minidump (stop the debugging and start it again). You see that the stack trace is now recovered correctly. But there is still one problem - the correct source code files are not displayed. In the Call Stack window, double-click the topmost stack frame. A dialog titled 'Find Source: crashrpt.cpp' will appear. In this dialog, browse to the D:\Projects\CrashRptSaved\src\reporting\crashrpt folder. Now the correct source file should be displayed in Visual Studio source code window.

At this point, you should be able to read the minidump correctly. If there are still problems, follow the instructions below:

- Maybe correct matching binaries and/or PDB files weren't saved. Ensure you save excatly the same binaries and PDB files that were generated during the linking process.

- If symbols for some modules of your program are loaded, and you are still unable to read the stack trace, than there were no debugging symbols generated for the module where crash had occurred. Check that you set Program Database (/Zi) compiler flag and Generate Debug Info (/DEBUG) linker flag for all modules of your application. For additional info, see Enabling Program Database (/Zi, /DEBUG) in Release Configuration.

- If the stack trace is not as accurate as you expect, the reason may be code optimizations. However, this is not the reason to turn the optimizations off. Instead, you can manage some error log file which is not affected by optimizations.

## Opening Minidump in WinDbg

You can use WinDbg program from Microsoft Debugging Tools for Windows for opening crash minidumps. It is freely distributed.

Let's show how to use WinDbg using an example. Run the sample CrashRptTest application that presents in CrashRpt package, and then click the button to generate an exception. Then extract the crashdump.dmp file from the crash report, launch WinDbg, and open the crash dump by pressing CTRL+D.

Next, you need to set the symbol path for WinDbg with the .sympath command. Switch to the command window (ALT+1) and enter ``.sympath followed by a space followed by the semi-colon delimited list of directories to search.

    .sympath D:\CrashRptSaved\CrashRptTest_v1.1.0

Similarly you need to set the executable and source search paths with the .exepath and ``.srcpath commands.

    .exepath D:\CrashRptSaved\CrashRptTest_v1.1.0
    .srcpath D:\Projects\CrashRpt\CrashRptTest\src

The final step is to change the debugger context to the context record associated with the exception by entering the ``.ecxr command.

    .ecxr

If everything is configured correctly, you should now be able to walk the call stack, see local variables, and loaded modules. You can even have WinDbg highlight the offending line of code by double clicking the CrashRptTest frame in the Call Stack window (ALT+6). Note: The exact line number may be a little off due to linker optimizations.

If I've saved all the source code, should building from the source recreate the correct PDBs to be able to use them for reading the minidump?

No, the recreated PDB files will not be the same as the original ones. The recreated PDB files won't have matching time stamp (or GUID in a never versions of dbghelp). The building environment may also be different, so generated binaries may be different.

The recommended way is to save the original PDB files (that were produced when building the project), binary files (EXE and DLL) along with the source code.