What WinDbg does when your program stops working
WinDbg is a debugger — a tool that lets you look at what a program was doing the moment it crashed. When a Windows program stops unexpectedly, WinDbg can show you the exact line of code that failed, what data was in memory at that moment, and what other parts of the program were running. Instead of guessing why something broke, you get to see the actual sequence of events that led to the crash.
The crash itself leaves behind a file called a dump file (usually with a .dmp extension). This file is a snapshot of the program's memory at the moment it stopped. WinDbg reads this dump file and translates the raw memory data into something you can understand — showing you the call stack (the chain of functions that were running), variable values, and error codes.
You do not need the original program running to analyze a crash. You just need the dump file and WinDbg, which is free from Microsoft. This is why crash analysis with WinDbg is useful for troubleshooting problems on other people's computers or investigating crashes that happened hours ago.
Key Takeaways
- WinDbg reads dump files to show you the exact code and data state when a program crashed, without needing the program to crash again.
- The call stack shows you the chain of functions running at the moment of the crash, with the failing function at the top.
- Common crash patterns — null pointer, buffer overflow, out-of-memory — each leave different clues in the dump file that WinDbg displays.
- You need the matching symbol files (PDB files) for WinDbg to show you actual function names and line numbers instead of memory addresses.
- The first step is always to look at the exception code and the call stack, which together tell you what failed and why.
Opening a dump file and reading the call stack
Start by opening WinDbg and loading the dump file. Go to File > Open Crash Dump, then select the .dmp file. WinDbg will load the file and show you an initial summary, including the exception code (the type of error that occurred) and the process ID.
The most important thing to look at first is the call stack. Type the command !analyze -v into the command window at the bottom of WinDbg. This command tells WinDbg to examine the crash and display a verbose analysis. The output will show you a stack trace — a list of functions that were running, in order from the innermost (the one that crashed) to the outermost.
The function at the top of the stack is where the crash happened. Look at the module name (the DLL or EXE file) and the function name. If you see something like ntdll!RaiseException or kernel32!RaiseException, the crash happened deep in Windows itself, which usually means the real problem is in the function that called it. Read down the stack until you find a function from the program you are debugging — that is where the actual bug lives.
Understanding exception codes and what they mean
The exception code is a hexadecimal number that tells you the category of error. The most common ones are:
0xC0000005 (Access Violation) means the program tried to read from or write to memory it does not own. This is usually a null pointer (trying to use a variable that was never set) or an out-of-bounds array access (reading past the end of a list). 0xC0000374 (Heap Corruption) means the program damaged the memory manager's internal structures, usually by writing past the end of a buffer. 0xC0000409 (Stack Overflow) means the program ran out of stack space, often because of infinite recursion or a function that allocates too much memory on the stack.
WinDbg will display the exception code prominently in the analysis output. If you see an access violation, your next step is to look at the registers and local variables to see what pointer was invalid. If you see heap corruption, look at what the program was writing to just before the crash.
Finding the exact line of code that failed
To see the actual source code line where the crash happened, you need symbol files (PDB files). These files contain the mapping between memory addresses and source code locations. Without them, WinDbg can only show you memory addresses and assembly instructions.
If you have the PDB files, configure WinDbg to find them. Go to File > Symbol File Path and add the folder where your PDB files are stored. Then reload the dump file. Now when you run !analyze -v, the call stack will show actual function names and line numbers instead of addresses.
If you do not have the PDB files, you can still see what the program was doing by reading the assembly code. Type u (unassemble) followed by the address of the failing function. This shows you the machine instructions, which is harder to read but still tells you what the code was trying to do.
Examining variables and memory at the crash point
Once you know which function crashed, look at the local variables and registers. Type dv (display variables) to see the values of all local variables at the crash point. This shows you what data the function was working with when it failed.
If you see a pointer variable that is zero or contains an invalid address, that is likely your culprit. If you see a string or buffer that looks corrupted or incomplete, that points to memory corruption. If you see a counter that is much larger than expected, that might explain an out-of-bounds access.
You can also examine memory directly. Type dd (display dword) or dq (display qword) followed by a memory address to see what is stored there. This is useful when a variable points to a structure and you want to see what is inside that structure.
Tracing backwards through the call stack to find the root cause
The function that crashed is not always the function with the bug. If function A calls function B, and function B crashes because function A passed it bad data, the bug is in function A, not function B.
Read up the call stack and look at each function. For each one, ask: did this function receive bad input from the function that called it? Did this function fail to check whether a pointer was valid before using it? Did this function allocate memory correctly?
Look at the parameters passed to the crashing function. Type dv /t to see the types of variables as well as their values. If a pointer parameter is zero or invalid, the bug is in the caller. If a size parameter is much larger than expected, that might explain why the function tried to access memory it should not have.
Using specialized commands for common crash patterns
WinDbg has commands for specific types of crashes. If you suspect heap corruption, type !heap -s to see the state of all heaps. If you suspect a null pointer, type !address to see what memory regions are allocated and what is not.
For multithreaded programs, type ~*k to see the call stacks of all threads. Sometimes the crashing thread is blocked waiting for another thread, and the real problem is in a different thread entirely. Look for threads that are stuck or doing something unexpected.
If the crash involves a specific Windows API call, search the Microsoft documentation for that API and its error codes. Many crashes happen because a program did not check the return value of a function call. Look at what the function returned and whether the program handled that return value correctly.
Frequently Asked Questions
Do I need the original program to analyze a crash with WinDbg?
No. You only need the dump file and WinDbg. The dump file contains a complete snapshot of the program's memory and state at the moment of the crash, so you can analyze it without the program running or even installed.
What if I do not have symbol files for the program?
You can still see what happened, but it is harder. WinDbg will show you memory addresses and assembly code instead of function names and line numbers. You can read the assembly to understand what the code was trying to do, but it requires more technical knowledge. Ask the program's developer for the PDB files if possible.
How do I know if the crash is in my code or in a library I am using?
Look at the module name in the call stack. If it says your program's name (like myprogram.exe), the crash is in your code. If it says a DLL name (like kernel32.dll or a third-party library), the crash is in that library. Read up the stack to find the last function from your program — that is where your code called the library incorrectly.
Can I use WinDbg to debug a program that is still running?
Yes, but that is a different workflow. You would attach WinDbg to the running process instead of opening a dump file. However, analyzing a dump file is usually easier because you can take your time without the program running.
What does "the exception was thrown in the wrong process" mean?
This message appears when the dump file is from a 32-bit program but you are running 64-bit WinDbg, or vice versa. read the matching version of WinDbg (32-bit or 64-bit) for the program that crashed, or use the multi-architecture version of WinDbg that Microsoft provides.