XNA Developer Connection (XDC)
December 2005
Not all bugs can be found prior to release, which means not all bugs that throw exceptions can be found before release. Fortunately, Microsoft has included in the Platform SDK a function to help developers collect information on exceptions discovered by users. The MiniDumpWriteDump function writes the necessary crash dump information to file without saving the whole process space. This crash dump information file is called a minidump.
This technical article covers the following topics:
The basic options for writing a minidump are as follows:
Do nothing. Windows automatically generates a minidump whenever a program throws an unhandled exception. Automatic generation of a minidump is only available on Windows XP and Windows Vista. If the user allows it, the minidump will be sent to Microsoft, and not to the developer, via Microsoft Windows Error Reporting (WER). Developers can contact the Microsoft Windows Gaming & Graphics developer relations group to arrange for access to the WER service.
Use of WER requires:
If you implement a custom routine for unhandled exceptions, you are strongly urged to use the ReportFault function in the exception handler to also send an automated minidump to WER. The ReportFault function handles all of the issues of connecting to and sending the minidump to WER. Not sending minidumps to WER violates the Games for Windows requirements.
For more information on how WER works, see How Windows Error Reporting Works. For an explanation of registration details, see Introducing Windows Error Reporting on MSDN's ISV Zone.
MiniDumpWriteDump is part of the DBGHELP library. This library is not thread-safe, so any program using MiniDumpWriteDump should synchronize all threads before attempting to call MiniDumpWriteDump.
The actual implementation is straightforward. The following is a simple example of how to use MiniDumpWriteDump.
#include#include #include int GenerateDump(EXCEPTION_POINTERS* pExceptionPointers) { BOOL bMiniDumpSuccessful; WCHAR szPath[MAX_PATH]; WCHAR szFileName[MAX_PATH]; WCHAR* szAppName = L"AppName"; WCHAR* szVersion = L"v1.0"; DWORD dwBufferSize = MAX_PATH; HANDLE hDumpFile; SYSTEMTIME stLocalTime; MINIDUMP_EXCEPTION_INFORMATION ExpParam; GetLocalTime( &stLocalTime ); GetTempPath( dwBufferSize, szPath ); StringCchPrintf( szFileName, MAX_PATH, L"%s%s", szPath, szAppName ); CreateDirectory( szFileName, NULL ); StringCchPrintf( szFileName, MAX_PATH, L"%s%s//%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", szPath, szAppName, szVersion, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, GetCurrentProcessId(), GetCurrentThreadId()); hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); ExpParam.ThreadId = GetCurrentThreadId(); ExpParam.ExceptionPointers = pExceptionPointers; ExpParam.ClientPointers = TRUE; bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL); return EXCEPTION_EXECUTE_HANDLER; } void SomeFunction() { __try { int *pBadPtr = NULL; *pBadPtr = 0; } __except(GenerateDump(GetExceptionInformation())) { } }
This example demonstrates the basic usage of MiniDumpWriteDump and the minimum information necessary to call it. The name of the dump file is up to the developer; however, it is advisable to generate the file name from the application's name and version number, the process and thread IDs, and the date and time to avoid file name collisions. This will also help to keep the minidumps grouped by application and version. It is up to the developer how much or little information is used to differentiate minidump file names.
It should be noted that the path name in the preceding example was generated by calling the GetTempPath function to retrieve the path of the directory designated for temporary files. Use of this directory works even with least-privileged user accounts, and it also prevents the minidump from taking up hard drive space after it is no longer needed.
If you archive the product during your daily build process, also be sure to include symbols for the build so that if you need to debug an old version of the product, you can. You also need to take steps to maintain full compiler optimizations while generating symbols. This can be done by opening your project's properties in the development environment and, for the release configuration, doing the following:
MSDN has more detailed information on the MINIDUMP_EXCEPTION_INFORMATION structure and the MiniDumpWriteDump function.
Dumpchk.exe is a command-line utility that can be used to verify that a dump file was created correctly. If Dumpchk.exe generates an error, then the dump file is corrupt and cannot be analyzed. For information on using Dumpchk.exe, see How to Use Dumpchk.exe to Check a Memory Dump File.
Dumpchk.exe is included on the Windows XP product CD and can be installed to System Drive/Program Files/Support Tools/ by running Setup.exe in the Support/Tools/ folder on the Windows XP product CD.
Opening a minidump for analysis is as easy as creating one.
To analyze a minidump
The debugger will create a simulated process. The simulated process will be halted at the instruction that caused the crash.
To get the stack for driver- or system-level crashes, it might be necessary to configure Visual Studio to point to the Microsoft public symbol server.
To set a path to the Microsoft symbol server
You can also use WinDbg, a debugger that is part of the Windows Debugging Tools, to debug a minidump. WinDbg allows you to debug without having to use Visual Studio. To download Windows Debugging Tools, see Windows Debugging Tools on Windows Hardware Developer Central.
After installing Windows Debugging Tools, you must enter the symbol path in WinDbg.
To enter a symbol path in WinDbg
In the Symbol Search Path window, enter the following:
"srv*c:/cache*http://msdl.microsoft.com/download/symbols;"
Developers also need to be aware of how their copy-protection scheme might affect the minidump. Most copy-protection schemes have their own descramble tools, and it is up to the developer to learn how to use those tools with MiniDumpWriteDump.
The MiniDumpWriteDump function can be an extremely useful tool in collecting and solving bugs after the product has been released. Writing a custom exception handler that uses MiniDumpWriteDump allows the developer to customize the information collection and improve the debugging process. The function is flexible enough to be used in any C++-based project and should be considered part of any project's stability process.