Forem

Cover image for How I Analyze C++ Crash Dumps Without WinDbg
Keith Pottratz
Keith Pottratz

Posted on

How I Analyze C++ Crash Dumps Without WinDbg

Every C++ developer has been here.

Your app crashed in production. A user sends you a .dmp file. You open it in WinDbg, spend 45 minutes configuring symbol paths, fight with .symfix, and eventually get a stack trace that may or may not be symbolicated correctly.

Most developers just skip the dump entirely and ask the user to describe what they were doing when it crashed.

That's not debugging. That's guessing.


The Problem With Crash Dumps Today

Crash dumps are genuinely useful. A minidump contains the exception type, the faulting address, the full call stack at the moment of the crash, every loaded module and its base address, and thread state. Everything you need to find the bug.

But the tooling is terrible for most developers:

  • WinDbg powerful but has a steep learning curve and requires significant setup
  • Visual Studio better UX but still needs symbol paths configured correctly
  • Manual DbgHelp you're writing your own tooling from scratch

For game developers especially, Unreal Engine crashes add another layer UE has its own crash reporter, its own log format, and its own symbol conventions that don't map cleanly to standard Windows tooling.

So, I built my own solution.


Step 1: Automatic Crash Dumps With One Line of Code

The first problem is actually getting the crash dump. A lot of C++ apps don't write one by default.

I built CrashCatch a free, open-source, header-only C++ library that hooks Windows structured exception handling and writes a minidump automatically when your app crashes.

#include "CrashCatch.hpp"

int main() {
    CrashCatch::enable();
    // your application code
}
Enter fullscreen mode Exit fullscreen mode

That's it. No dependencies. No config required. Drop the header in, add one line, and from that point on every crash writes a .dmp file to disk.

The SDK is on GitHub (Apache 2.0): github.com/keithpotz/CrashCatch

It uses SetUnhandledExceptionFilter under the hood and calls MiniDumpWriteDump from DbgHelp. You can configure the dump type (MiniDumpNormal, MiniDumpWithFullMemory, etc.) and the output path.


Step 2: Reading the Dump The Interesting Part

Once you have the .dmp file, you need to actually read it. This is where I spent most of my engineering time.

I built an analysis engine in C++ using:

  • DbgHelp for stack walking (StackWalk64) and symbol resolution (SymFromAddr)
  • DIA SDK for reading PDB files and resolving symbols to source file + line number
  • MINIDUMP_EXCEPTION_STREAM for parsing the exception record
  • MINIDUMP_MODULE_LIST for enumerating loaded modules

The result is a structured CrashReport object that contains:

exception_code:     0xC0000005 (ACCESS_VIOLATION)
exception_address:  0x00007FF6A3B2C140
faulting_module:    MyGame.exe
access_violation:   read at 0x0000000000000000

stack_trace:
  [0] AEnemy::Tick(float) — AEnemy.cpp:247
  [1] UActorComponent::TickComponent(float, ...) — ActorComponent.cpp:412
  [2] FActorTickFunction::ExecuteTick(...) — Actor.cpp:88
Enter fullscreen mode Exit fullscreen mode

That null pointer read at frame 0 tells you everything.



The Intel Engine

One thing I'm particularly happy with is what I call the Intel engine a pattern-matching layer that runs before any AI.

It looks at the exception code, faulting module, access violation address, and stack signatures and produces a structured diagnosis:

  • 0xC0000005 read at 0x0 → null pointer dereference, points at frame 0 as likely cause
  • 0xC0000005 write at a high address → stack corruption or buffer overflow
  • 0xC0000409 → stack overflow, check for infinite recursion
  • Exception in a known UE module → UE-specific context added automatically

This means even without an internet connection or API key, you get a useful diagnosis immediately. The AI layer builds on top of this it doesn't replace it.

dump explination


Explain Mode

Once the Intel engine has run, you can hit Explain Mode. This sends the structured crash report to Claude (Anthropic) and gets back:

  • Plain-English explanation of what happened
  • Root cause analysis
  • Specific suggestions for what to fix

For the null pointer crash above it comes back with something like:

"The crash occurred in AEnemy::Tick at line 247 of AEnemy.cpp. The access violation at address 0x0 indicates a null pointer dereference — something the Tick function is trying to read from is null. Check that any UObject references or pointers used in Tick are validated before access, particularly any references that could be destroyed between frames."

That's the kind of answer that takes a junior developer 20 minutes to arrive at. It's there in 3 seconds.


Unreal Engine Support

Unreal Engine deserves its own mention. CrashCatch Analyze detects UE projects automatically and:

  • Parses UE log output alongside the dump
  • Identifies UE-specific exception patterns
  • Shows a dedicated UE context tab with engine version, project name, and relevant log lines
  • Handles UE's symbol conventions correctly

If you're shipping an Unreal Engine game, you can point CrashCatch at your project folder and it handles the rest.


The Desktop App

I wrapped all of this in a native Windows desktop app built with Tauri 2 a Rust backend with a TypeScript/WebView2 frontend. The analysis engine is a C++ DLL called via Rust FFI.

The workflow:

  1. Drag a .dmp file onto the drop zone
  2. (Optional) Set your symbol paths
  3. Analysis runs in under a second
  4. Navigate the tabs: Stack Trace, Exception, Modules, Intel, UE Context, Explain, Raw
  5. Export to PDF if you need to share it with your team

home page


Where To Get It

CrashCatch SDK free, open source, Apache 2.0:
github.com/keithpotz/CrashCatch

CrashCatch Analyze native Windows desktop app, currently in beta:
crashcatchlabs.com

If you're shipping a C++ app on Windows and you're not collecting crash dumps, start with the SDK. It's one line of code and costs you nothing.

If you already have .dmp files piling up and no good way to read them — that's what the analyzer is for.


Questions about the DbgHelp / DIA SDK internals, the Tauri + native DLL architecture, or the Unreal Engine integration? Ask in the comments.


Top comments (0)