13

I am trying to create a dump file for my application whenever it crashes. I am currently using procdump.exe with -e flag in order to do it, so if I have unhandled exception in my application procdump creates a dump file for me.

I thought that I was done, but then I found out that my application crashes and procdump doesn’t create a dump file. After some investigations I have found out that invalid use of vector::front causes runtime error. I turned on the _SECURE_SCL_THROWS flag and after that procdump.exe -e did catch the crash and created a dump file.

Now to my question: Is now procdump.exe -e will always create a dump file when my application crashes? How can I guarantee that I don’t have any other scenarios where procdump -e is not good for me?

Lior Ashkenazi
  • 131
  • 1
  • 1
  • 5

3 Answers3

14

I assume you are on a windows environment (because you use procdump.exe). You could also set an exception filter for your programm that writes a mindump whenever your application crash:

  1. Register a callback function using SetUnhandledExceptionFilter which will be invoked on a crash. A possible signature would be:

    LONG WINAPI HandleException(struct _EXCEPTION_POINTERS* apExceptionInfo)
    

    Register it somewhere using:

    SetUnhandledExceptionFilter(HandleException);   
    
  2. Define a function pointer to call the Function MiniDumpWriteDump:

    typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,CONSTPMINIDUMP_USER_STREAM_INFORMATIOUserStreamParam,CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
    
  3. Use the MiniDumpWriteDump function to write the dump (requires DbgHelp.dll 5.1 or later) in the previously registerd callback method (HandleException):

    HMODULE mhLib = ::LoadLibrary(_T("dbghelp.dll"));
    MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(mhLib, "MiniDumpWriteDump");
    
    HANDLE  hFile = ::CreateFile(_T("dump_name"), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
                        FILE_ATTRIBUTE_NORMAL, NULL);
    
    
    _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
    ExInfo.ThreadId = ::GetCurrentThreadId();
    ExInfo.ExceptionPointers = apExceptionInfo;
    ExInfo.ClientPointers = FALSE;
    
    pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL);
    ::CloseHandle(hFile);
    
Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
  • Why are you using `GetProcAddr` for `MiniDumpWriteDump` when you can just include DbgHelp.h from the DebuggingTools SDK?? – Martin Ba Nov 27 '12 at 18:29
  • Because the IAT (Import Address Table) may be already corrupted when the crash occurs. In such crash handlers, the only reliable thing to do is to link with libraries by yourself! – Петър Петров Feb 11 '16 at 12:54
  • @ПетърПетров But then how are you going to call `LoadLibrary`? If the IAT is corrupted, then you're probably already screwed. – LHLaurini Feb 13 '16 at 16:23
  • Sometimes the IAT will not be corrupted, but other internal states on win32 subsystems will be, for example CreateFileA/W will not work but LoadLibrary usually works. If the IAT is corrupted, It will crash immediately anyway. I had noticed that kernel32.dll functions worked when IAT is corrupted on x64 win7... Which is strange. – Петър Петров Feb 20 '16 at 17:16
11

/* WinDump.cpp */

#ifdef WIN32

#include <windows.h>
#include <Dbghelp.h>
#include <tchar.h>


typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);

void create_minidump(struct _EXCEPTION_POINTERS* apExceptionInfo)
{
    HMODULE mhLib = ::LoadLibrary(_T("dbghelp.dll"));
    MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(mhLib, "MiniDumpWriteDump");

    HANDLE  hFile = ::CreateFile(_T("core.dmp"), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL, NULL);

    _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
    ExInfo.ThreadId = ::GetCurrentThreadId();
    ExInfo.ExceptionPointers = apExceptionInfo;
    ExInfo.ClientPointers = FALSE;

    pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL);
    ::CloseHandle(hFile);
}

LONG WINAPI unhandled_handler(struct _EXCEPTION_POINTERS* apExceptionInfo)
{
    create_minidump(apExceptionInfo);
    return EXCEPTION_CONTINUE_SEARCH;
}

#endif // WIN32

/* WinDump.h */

#ifdef WIN32

LONG WINAPI unhandled_handler(struct _EXCEPTION_POINTERS* apExceptionInfo);

#endif // WIN32

/* main.cpp */

#include "WinDump.h"

int main(int argc, char **argv)
{

    // Create a dump file whenever the gateway crashes only on windows
    SetUnhandledExceptionFilter(unhandled_handler);
    return 0;
}
Praveen
  • 111
  • 1
  • 2
1

Or use Windows' built in error reporting, WER, by adding a key to registry, to enable it for your app. More details here: https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps

mBardos
  • 2,872
  • 1
  • 19
  • 16