Prolific Usage of MiniDumpWriteDump (Automating Crash Dump Analysis Part 0)

As a precursor to a series on programmatically querying crash dump files, I wanted to first talk about the MiniDumpWriteDump function.

 

You don't necessarily need to wait for your application to crash in order to generate a memory dump. As soon as you detect something bad happening, you can call MiniDumpWriteDump yourself and generate a crash dump file on the fly. If your application likes to eat exceptions or ignore error codes, or important asserts fire, or special test cases fail, then this is a great place to start collecting failure data for offline analysis.

 

And to make it super easy for you, I've created a helper function which will generate a filename based on the computer's name along with the date and time, then invoke the crash dump generator.

 

#include <dbghelp.h>

 

HRESULT GenerateCrashDump(MINIDUMP_TYPE flags, EXCEPTION_POINTERS *seh=NULL)

    {

    HRESULT error = S_OK;

 

    // get the time

    SYSTEMTIME sysTime = {0};

    GetSystemTime(&sysTime);

 

    // get the computer name

    char compName[MAX_COMPUTERNAME_LENGTH + 1] = {0};

    DWORD compNameLen = ARRAYSIZE(compName);

    GetComputerNameA(compName, &compNameLen);

 

    // build the filename: APPNAME_COMPUTERNAME_DATE_TIME.DMP

    char path[MAX_PATH] = {0};

    sprintf_s(path, ARRAYSIZE(path),

        "c:\\myapp_%s_%04u-%02u-%02u_%02u-%02u-%02u.dmp",

    compName, sysTime.wYear, sysTime.wMonth, sysTime.wDay,

        sysTime.wHour, sysTime.wMinute, sysTime.wSecond);

 

    // open the file

    HANDLE hFile = CreateFileA(path,

        GENERIC_READ|GENERIC_WRITE,

        FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,

        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

 

    if(hFile == INVALID_HANDLE_VALUE)

        {

        error = GetLastError();

        error = HRESULT_FROM_WIN32(error);

        return error;

        }

 

    // get the process information

    HANDLE hProc = GetCurrentProcess();

    DWORD procID = GetProcessId(hProc);

 

    // if we have SEH info, package it up

    MINIDUMP_EXCEPTION_INFORMATION sehInfo = {0};

    MINIDUMP_EXCEPTION_INFORMATION *sehPtr = NULL;

    if(seh)

        {

        sehInfo.ThreadId = GetCurrentThreadId();

        sehInfo.ExceptionPointers = seh;

        sehInfo.ClientPointers = FALSE;

        sehPtr = &sehInfo;

        }

 

    // generate the crash dump

    BOOL result = MiniDumpWriteDump(hProc, procID, hFile,

        flags, sehPtr, NULL, NULL);

 

    if(!result)

        {

        error = (HRESULT)GetLastError(); // already an HRESULT

        }

 

    // close the file

    CloseHandle(hFile);

 

    return error;

    }

 

Sample call:

    GenerateCrashDump((MINIDUMP_TYPE)

        (MiniDumpNormal |

        MiniDumpWithHandleData |

        MiniDumpWithUnloadedModules),

        NULL);

 

If you happen to have OS exception information available (via __try/__except), then you will definitely want to pass in the EXCEPTION_POINTERS information. This will embed important and detailed information about the exception into the crash dump.

And if you want to get really fancy, you can embed additional (custom) information via the 2nd to last parameter to MiniDumpWriteDump. For example, if your application is consuming external documents or information, it can be very handy to have this information (or metadata about it) accessible when diagnosing crash dumps after the fact.

Comments

  • Anonymous
    May 27, 2008
    So let's assume for the moment that you have a collection of crash dump files from your team's application.

  • Anonymous
    June 02, 2008
    So now that we have a memory dump file , and know how to open it , we will want to pull some useful data

  • Anonymous
    June 23, 2008
    For a reference, here are some links to the previous parts in this series: ยท Prolific Usage of MiniDumpWriteDump

  • Anonymous
    December 20, 2010
    It's worth noting that this helper function will usually not generate valid a call stack for the thread from which it is called, if no EXCEPTION_POINTERS info is provided.  One simple fix is to just create a separate worker thread to call MiniDumpWriteDump from and then wait for it to complete, within this helper function...