How to write Mini Dump on software crash

Sorry for not writing anything interesting this month so far, it’s been a very hectic month.

Today I saw a question on Stack Overflow regarding debugging. The user was trying to let Visual Studio run in debug mode with his application to see when and why it crashes.

That’s not a solution because there are functions in place for these situations in Windows API. More simply put, you can make your software write a Mini Dump upon crash and then you can just open it inside Visual Studio (or whatever debugger you want) and see exactly where it crashed.

The below example is ready to use for any .exe or .dll on Windows:

#pragma once

#include <Windows.h>
#include <Dbghelp.h>
#pragma comment (lib, "Dbghelp.lib")

// Because... why not ?!
namespace MecanikUtils
{
	LPTOP_LEVEL_EXCEPTION_FILTER PreviousExceptionFilter = 0;

	LONG WINAPI DumpExceptionFilter(EXCEPTION_POINTERS* info)
	{
		wchar_t DumpPath[MAX_PATH] = { 0 };

		SYSTEMTIME SystemTime;
		GetLocalTime(&SystemTime);

		WCHAR szExeFileName[100] = { 0 };
		GetModuleFileNameW(NULL, szExeFileName, 99);

		wsprintfW(DumpPath, L"Crash_%s_%d-%d-%d_%dh%dm%ds.dmp", szExeFileName, SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond);

		HANDLE file = CreateFileW(DumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

		if (file != INVALID_HANDLE_VALUE)
		{
			MINIDUMP_EXCEPTION_INFORMATION mdei;

			mdei.ThreadId = (DWORD)GetCurrentThreadId();

			mdei.ExceptionPointers = info;

			mdei.ClientPointers = 0;

			if (MiniDumpWriteDump(GetCurrentProcess(), (DWORD)GetCurrentProcessId(), file, (MINIDUMP_TYPE)(MiniDumpScanMemory + MiniDumpWithIndirectlyReferencedMemory), &mdei, 0, 0) != 0)
			{
				CloseHandle(file);
				return EXCEPTION_EXECUTE_HANDLER;
			}
		}

		CloseHandle(file);

		return EXCEPTION_CONTINUE_SEARCH;
	}

	class MiniDump
	{
	public:

		/// <summary>
		/// Add Unhandled Exception Filter
		/// </summary>
		inline static void Init()
		{
			// Change if required
			SetErrorMode(SEM_FAILCRITICALERRORS);

			PreviousExceptionFilter = SetUnhandledExceptionFilter(DumpExceptionFilter);
		}

		/// <summary>
		/// Remove Unhandled Exception Filter
		/// </summary>
		inline static void Clean()
		{
			SetUnhandledExceptionFilter(PreviousExceptionFilter);
		}
	};
}

To use it simply call the following at the start + end of your software’s entry point. For example a .dll:

#include "MiniDump.hpp"

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
   switch ( ul_reason_for_call )
   {
      case DLL_PROCESS_ATTACHED:
      MecanikUtils::MiniDump::Init();
      break;
      
      case DLL_PROCESS_DETACH:
      MecanikUtils::MiniDump::Clean();
      break;
   }
   return TRUE;
}

Feel free to make changes to SetErrorMode if you need to.

Note: Keep the original .pdb of the compiled .exe/.dll if you want to open the Mini Dump. Otherwise you won’t have any easy readable information.

Until next time! 🙂

Liked it? Support me on Patreon with a coffee 😀

2 comments

  1. Simple, elegant, convenient. And wrong.

    As documented, “MiniDumpWriteDump should be called from a separate process if at all possible”. There’s little more information, and finding out what can go wrong if you don’t is left as an exercise to users of this API.

    I have, and the TL;DR is: MiniDumpWriteDump will deadlock your process, leaving you empty-handed.

    MiniDumpWriteDump puts the target process into a stable state. It does so by suspending all threads at the time of call. It doesn’t attempt to check, whether those threads are in a “safe” state. It just suspends them, whatever they are doing. Or whichever global lock they are currently holding. If a thread was in the middle of loading a library it will now indefinitely hold the loader lock. The moment your code tries to do the same, directly or indirectly, you have an instant deadlock. Not scary enough? What about a thread that was just new’ing up some memory and holds the global process heap’s lock? MiniDumpWriteDump will allocate memory from the process heap, and when it does it will now deadlock.

    There are really just two reliable options: Set up Windows Error Reporting to capture a minidump on crash, or move MiniDumpWriteDump to an external process in case you need special features, such as writing a dump in cases other than a crash, or more fine-grained control over what goes into your minidump.

    1. This is indeed correct, however very inconvenient to write a separate process for this purpose most of the times. This article is purely a simple “way” of writing process dumps in case of failure, I will post a better example example soon 🙂

Leave a comment

Your email address will not be published. Required fields are marked *