<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Keith Pottratz</title>
    <description>The latest articles on Forem by Keith Pottratz (@crashcatchlabs).</description>
    <link>https://forem.com/crashcatchlabs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3841792%2F5bbb78f3-f9e4-4d1d-9e80-fb67287002b6.png</url>
      <title>Forem: Keith Pottratz</title>
      <link>https://forem.com/crashcatchlabs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/crashcatchlabs"/>
    <language>en</language>
    <item>
      <title>How I Analyze C++ Crash Dumps Without WinDbg</title>
      <dc:creator>Keith Pottratz</dc:creator>
      <pubDate>Tue, 24 Mar 2026 15:44:29 +0000</pubDate>
      <link>https://forem.com/crashcatchlabs/how-i-analyze-c-crash-dumps-without-windbg-ejm</link>
      <guid>https://forem.com/crashcatchlabs/how-i-analyze-c-crash-dumps-without-windbg-ejm</guid>
      <description>&lt;p&gt;Every C++ developer has been here.&lt;/p&gt;

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

&lt;p&gt;Most developers just skip the dump entirely and ask the user to describe what they were doing when it crashed.&lt;/p&gt;

&lt;p&gt;That's not debugging. That's guessing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem With Crash Dumps Today
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;But the tooling is terrible for most developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WinDbg&lt;/strong&gt; powerful but has a steep learning curve and requires significant setup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual Studio&lt;/strong&gt; better UX but still needs symbol paths configured correctly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual DbgHelp&lt;/strong&gt; you're writing your own tooling from scratch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;So, I built my own solution.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Automatic Crash Dumps With One Line of Code
&lt;/h2&gt;

&lt;p&gt;The first problem is actually &lt;em&gt;getting&lt;/em&gt; the crash dump. A lot of C++ apps don't write one by default.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;CrashCatch&lt;/strong&gt; a free, open-source, header-only C++ library that hooks Windows structured exception handling and writes a minidump automatically when your app crashes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"CrashCatch.hpp"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;CrashCatch&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;enable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// your application code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The SDK is on GitHub (Apache 2.0): &lt;a href="https://github.com/keithpotz/CrashCatch" rel="noopener noreferrer"&gt;github.com/keithpotz/CrashCatch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It uses &lt;code&gt;SetUnhandledExceptionFilter&lt;/code&gt; under the hood and calls &lt;code&gt;MiniDumpWriteDump&lt;/code&gt; from DbgHelp. You can configure the dump type (MiniDumpNormal, MiniDumpWithFullMemory, etc.) and the output path.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Reading the Dump The Interesting Part
&lt;/h2&gt;

&lt;p&gt;Once you have the &lt;code&gt;.dmp&lt;/code&gt; file, you need to actually read it. This is where I spent most of my engineering time.&lt;/p&gt;

&lt;p&gt;I built an analysis engine in C++ using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DbgHelp&lt;/strong&gt; for stack walking (&lt;code&gt;StackWalk64&lt;/code&gt;) and symbol resolution (&lt;code&gt;SymFromAddr&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DIA SDK&lt;/strong&gt; for reading PDB files and resolving symbols to source file + line number&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MINIDUMP_EXCEPTION_STREAM&lt;/strong&gt; for parsing the exception record&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MINIDUMP_MODULE_LIST&lt;/strong&gt; for enumerating loaded modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a structured &lt;code&gt;CrashReport&lt;/code&gt; object that contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That null pointer read at frame 0 tells you everything.&lt;/p&gt;







&lt;h2&gt;
  
  
  The Intel Engine
&lt;/h2&gt;

&lt;p&gt;One thing I'm particularly happy with is what I call the &lt;strong&gt;Intel engine&lt;/strong&gt; a pattern-matching layer that runs &lt;em&gt;before&lt;/em&gt; any AI.&lt;/p&gt;

&lt;p&gt;It looks at the exception code, faulting module, access violation address, and stack signatures and produces a structured diagnosis:&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgwml4xggpp7p1zrwh4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgwml4xggpp7p1zrwh4l.png" alt="dump explination" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Explain Mode
&lt;/h2&gt;

&lt;p&gt;Once the Intel engine has run, you can hit &lt;strong&gt;Explain Mode&lt;/strong&gt;. This sends the structured crash report to Claude (Anthropic) and gets back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Plain-English explanation of what happened&lt;/li&gt;
&lt;li&gt;Root cause analysis&lt;/li&gt;
&lt;li&gt;Specific suggestions for what to fix&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the null pointer crash above it comes back with something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"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."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the kind of answer that takes a junior developer 20 minutes to arrive at. It's there in 3 seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  Unreal Engine Support
&lt;/h2&gt;

&lt;p&gt;Unreal Engine deserves its own mention. CrashCatch Analyze detects UE projects automatically and:&lt;/p&gt;

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

&lt;p&gt;If you're shipping an Unreal Engine game, you can point CrashCatch at your project folder and it handles the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Desktop App
&lt;/h2&gt;

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

&lt;p&gt;The workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Drag a &lt;code&gt;.dmp&lt;/code&gt; file onto the drop zone&lt;/li&gt;
&lt;li&gt;(Optional) Set your symbol paths&lt;/li&gt;
&lt;li&gt;Analysis runs in under a second&lt;/li&gt;
&lt;li&gt;Navigate the tabs: Stack Trace, Exception, Modules, Intel, UE Context, Explain, Raw&lt;/li&gt;
&lt;li&gt;Export to PDF if you need to share it with your team&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24eg1y315bgtzxs4ut7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24eg1y315bgtzxs4ut7w.png" alt="home page" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Where To Get It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CrashCatch SDK&lt;/strong&gt; free, open source, Apache 2.0:&lt;br&gt;
&lt;a href="https://github.com/keithpotz/CrashCatch" rel="noopener noreferrer"&gt;github.com/keithpotz/CrashCatch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CrashCatch Analyze&lt;/strong&gt; native Windows desktop app, currently in beta:&lt;br&gt;
&lt;a href="https://crashcatchlabs.com" rel="noopener noreferrer"&gt;crashcatchlabs.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;If you already have &lt;code&gt;.dmp&lt;/code&gt; files piling up and no good way to read them — that's what the analyzer is for.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Questions about the DbgHelp / DIA SDK internals, the Tauri + native DLL architecture, or the Unreal Engine integration? Ask in the comments.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>cpp</category>
      <category>gamedev</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
