Troubleshooting · Crash evidence
How to investigate repeated BSODs with minidumps and Windows crash evidence
A machine that bluescreens once gives you an event. A machine that bluescreens repeatedly gives you something rarer and more useful: a dataset. Repetition means the fault is reproducible, and a reproducible fault leaves a trail — dump files, event-log entries, timestamps — that you can follow instead of guessing through. This guide is about following that trail properly: from the files Windows writes at each crash, through the debugger output, to a conclusion you can actually defend.
The principle that runs through every section: a module named in a crash dump is evidence, not a verdict. The debugger can tell you where the crash landed and which module was executing when it did. It cannot, by itself, tell you what corrupted the data or wrote the bad pointer. Most misdiagnosed BSODs — and most unnecessary part replacements — happen in the gap between "where it crashed" and "why it crashed".
What you'll do here, in order: confirm Windows is actually producing dumps, verify they match the crashes you're investigating, open them in WinDbg with working symbols, read the bug check and its parameters, interpret the blamed module and the stack without over-reading either, compare multiple dumps to separate a repeated cause from a repeated symptom, and use Event Viewer, Reliability Monitor, and — only when appropriate — Driver Verifier to test competing explanations. Every step has a deeper guide in the cluster linked throughout.
Check the timestamp before you analyze anything.
The most common analytical error is analyzing a stale dump — one written by a crash you already fixed, or a crash with a different cause than the one you're chasing. Before opening a dump, confirm its file date matches the crash you're investigating. The file's date is evidence too; a mismatch changes the whole analysis.
The mindset
What a repeated BSOD actually gives you
A single crash can be noise: a transient glitch, a one-off power dip, a momentary driver hiccup that never repeats. Three crashes with the same bug check code and a similar stack are not noise — they're a pattern you can test. That's the whole case for working with dumps at all. Repetition converts "something bad happened" into "the same failure mode is happening, and it will happen again in a way I can observe".
It helps to be precise about what each stage of an investigation is. An observation is what a tool shows you: a dump exists, its bug check is 0xd1, its SYMBOL_NAME is extmon!ExtIoControl+1a4. An inference is what you draw from observations: the crash involves that driver's I/O path. A hypothesis is a testable claim: this driver build is at fault. Confirmation is a prediction that held: after changing exactly that variable, the specific code stopped appearing under real use. Most failed investigations are a stage skipped — a hypothesis announced as a confirmation, or an observation (a module in a stack) read as a cause.
The unit of evidence for each crash is a small bundle: the bug check code, its parameters, the stack, the blamed module (if symbols resolved), and a timestamp. Individually each item is weak. Assembled across several crashes into a timeline, they're usually enough to rank the plausible causes — which is exactly what the rest of this guide operationalizes, starting with where to find the bundle.
The evidence map
Where Windows leaves crash evidence
The minidump is the star witness, but it isn't the only one — and it's not always present. Windows records a crash in several independent places, and the ones that survive a failed dump write are often enough to establish the code and parameters for correlation. Know the full map before you start, so a missing dump doesn't end the investigation.
| Source | Where to look | What it contributes |
|---|---|---|
| Minidump files | C:\Windows\Minidump | A slice of kernel state at the crash: stack, module list, basic context |
| Kernel / automatic dump | MEMORY.DMP at the system drive root | A larger slice with more process and thread data |
| Event ID 1001 (BugCheck) | Event Viewer → System log | Bug check code and parameters — written even when a dump is not |
| Event ID 41 (Kernel-Power) | Event Viewer → System log | An unexpected shutdown; a code of 0 often means power, not a driver |
| WHEA-Logger events (19 / 31) | Event Viewer → System log | Hardware error records (memory, CPU) — an explicit hardware signal |
| Reliability Monitor | reladmin /reliability | A consolidated timeline of problem events, good for spotting "crashes started after X" |
Two rows deserve emphasis. Event 1001 means you can build a correlation table of codes and parameters without any dump at all — useful when dumps are disabled or the writer failed. And WHEA events are the clearest hardware tell in Windows: when they appear near crash times, the investigation shifts from "which driver" toward "which component", which changes the whole plan.
Collect evidence
Finding — and verifying — your minidumps
Minidumps land in C:\Windows\Minidump as files named with a timestamp, typically around 320 KB on a 64-bit system. If your dump type is Automatic or Kernel, the evidence is instead a single MEMORY.DMP at the root of your system drive — so an empty Minidump folder is not, by itself, proof that no dumps exist. List what's actually there, newest first:
Get-ChildItem $env:SystemRoot\Minidump -ErrorAction SilentlyContinue |
Sort-Object LastWriteTime -Descending |
Select-Object -First 10 Name, Length, LastWriteTime
The verification step most investigations skip is the one that saves the most time: matching a dump's LastWriteTime to the crash you're actually chasing. Dumps accumulate. If you've been through several distinct problems — a driver crash in week one, a power event in week three — the folder holds evidence for all of them, and analyzing the wrong one means "diagnosing" a problem you already solved. Pair each dump with its Event 1001 entry, whose timestamp and code should agree; disagreement is itself a finding worth noting.
Worth checking once, before you need it: whether dump writing is actually enabled at all. In System → About → Advanced system settings → Startup and Failure, the "Write debugging information" setting controls this — and None means no dump will ever be written, ending dump analysis before it starts. The same setting is readable from the command line:
Get-CimInstance Win32_OperatingSystem | Select-Object DebuggingMode
0 = none · 1 = kernel · 2 = small (256 KB) · 3 = complete · 4 = active memory · 7 = automatic. "Small" predates modern drivers and is generally not useful.
If the result is 0, set the type to Automatic (or Small, if you specifically want minidump files) and let the next crash generate evidence. You can't analyze what was never written.
Know the instrument
What a minidump can — and cannot — establish
A minidump is a targeted slice: the kernel stack at the moment of the crash, the module list, and enough context to attribute frames to functions (given symbols). That's why it's the right default for driver-crash work — it's small, always analyzable, and usually contains exactly the question you're asking. But its edges matter, because over-reading them is where false conclusions start.
What a minidump establishes: where the faulting instruction executed, which modules were in the stack, the bug check and its parameters, and (with symbols) the function names involved. What it does not establish: the contents of a corrupted data structure after the fact, who wrote a bad value, anything that happened in hardware before the fault reached the kernel, or events involving memory pages that weren't captured. A crash in a read of a pointer tells you the read failed; it does not tell you which driver, or which stick of RAM, put the bad value there.
| Dump type | Typical size | What you get | When it's the right choice |
|---|---|---|---|
| Minidump (Small memory) | ~320 KB (64-bit) | Kernel stack, module list, basic context | The default for driver-crash investigation |
| Kernel dump (MEMORY.DMP) | Hundreds of MB | Minidump content plus process and thread data | When you need per-process detail |
| Complete memory dump | Size of RAM | Everything in memory at the crash | Rarely; high storage and time cost, marginal gain for most crashes |
| Active memory dump | Portion of RAM in use | The live working set | Specific scenarios; not a general upgrade |
| Automatic memory dump | Windows decides | Usually a kernel dump | A fine default — check what it actually wrote |
One more edge case: some crashes produce no dump at all. A hard hang, or a fault severe enough to take down the dump writer itself, can leave Event 1001 without a file. The absence is evidence — it argues for a lower-level problem.
Prepare the tool
Setting up WinDbg and — more importantly — symbols
WinDbg comes from Microsoft's Debugging Tools for Windows (available with the Windows SDK). Install it once, and open a dump with File → Open Crash Dump. The installation is trivial; the part that determines whether your analysis is trustworthy is the symbol path.
Symbols are the debug databases that let the debugger translate addresses into function names. Without them, the single most useful field in the whole analysis — SYMBOL_NAME — degrades from extmon!ExtIoControl+1a4 to a bare offset or a question mark, and your ability to attribute a crash to a specific function (let alone a specific driver) drops sharply. Point WinDbg at Microsoft's public symbol server before your first analysis:
.symfix
.sympath srv*C:\symbols
First use downloads symbols on demand, so expect a pause the first time a module is resolved. Two things to know about symbol quality. First, verify that resolution actually worked: after opening a dump, run lmvm on the module of interest — the output shows whether its PDB was found.
lmvm extmon.sys
Replaces the example name with the module from your dump. Look for the PDB line: a resolved path means function names are real; "private pdb info" or a missing PDB means offsets only.
Second, many third-party drivers are shipped without public symbols at all. When that's the case you'll see offsets even with a perfect symbol path — the module attribution is still valid, but the function-level detail isn't, and any conclusion should be weighted accordingly. Note it in your investigation log; "no symbols for this driver" is a legitimate reason a case needs stronger corroborating evidence.
First analysis
Opening the dump and running the analysis
With the dump open and symbols pointed at the server, the starting command is !analyze -v — the automated analysis. It walks the crash state, looks up the bug check, resolves the modules in the stack, and prints a structured report. Treat it as a well-organized first read, not a verdict: it is a heuristic engine whose job is to surface the evidence, and every field it prints is still yours to interpret.
!analyze -v
The excerpt below is illustrative — the values are not from a real machine — but it shows the report's shape: the bug check block, the debugging-details fields, the stack, and the "Probably caused by" line that ends it. Walk down the report in that order, and you'll find every section of this guide maps onto a block of it.
DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pageable (or completely invalid)
address at an IRQL that is too high. This is usually caused by
drivers that have corrupted process or kernel memory.
Arguments:
Arg1: 00000000`deadbeef, memory address that was referenced
Arg2: 00000000`00000002, IRQL
Arg3: 00000000`00000001, 0 = read operation, 1 = write operation
Arg4: ffff...44, address of the instruction that referenced the address
Debugging Details:
------------------
MODULE_NAME: extmon
IMAGE_NAME: extmon.sys
SYMBOL_NAME: extmon!ExtIoControl+1a4
FAILURE_BUCKET_ID: AVDRV_c0000005_extmon.sys!ExtIoControl
BUGCHECK_STR: AVDRV
PROCESS_NAME: System
CURRENT_IRQL: 2
STACK_TEXT:
ffff...44 extmon!ExtIoControl+1a4
ffff...e2 nt!IopXxxControlFile+132
ffff...8a nt!KiSystemCall64+...
Followup: MachineOwner
---------
Probably caused by : extmon.sys ( extmon!ExtIoControl+1a4 )
Read the report top to bottom, but weight the middle: the BUGCHECK_* block is the most objective part, the module fields are where the interpretation begins, and the final line is where the over-interpretation usually happens. The next three sections take those blocks in order — bug check, module, stack.
The most objective block
Reading the bug check and its parameters
The bug check is the crash's classification: a code (0xd1), a mnemonic (AVDRV), and up to four parameters whose meaning depends on the code. It's the most objective field in the dump — the same code means the same class of fault on every machine — which is why it's the backbone of cross-dump correlation. If you ever need a code's name without a dump open, WinDbg looks it up:
!error 0xd1
Returns the bug check name for the code — useful for codes you see in Event Viewer before opening a dump.
Parameters are where most readers stop, but they're structured evidence. A 0xd1 tells you an invalid address was touched at an IRQL that was too high; its parameters tell you which address, at which IRQL, on a read or a write. A 0x1a (MEMORY_MANAGEMENT) encodes the corruption class in P1 — 0x139 for pool corruption, 0x143 for a double-freed block — and carries the four-character pool tag of the affected block in P3/P4, a tag that identifies the component that allocated the memory. That's rarer and stronger evidence than a module name: it's a signature left by the allocator, not a witness statement from the crash site.
| Code | Name | What the parameters carry |
|---|---|---|
| 0xd1 | DRIVER_IRQL_NOT_LESS_OR_EQUAL | P1 invalid address · P2 IRQL · P3 read(0)/write(1) · P4 faulting instruction |
| 0x50 | PAGE_FAULT_IN_NONPAGED_AREA | P1 faulting address · P2 read(0)/write(1) |
| 0x1a | MEMORY_MANAGEMENT | P1 corruption class (e.g. 0x139 pool corruption) · P3/P4 pool tag of the block |
| 0x124 | WHEA_UNCORRECTABLE_ERROR | P1 severity + error source · P2 physical address of the WHEA error record — a hardware signal |
Notice what even the most specific of these does not do: none of them names a component. They narrow the class of fault and, in the pool-tag case, point at an allocating subsystem. The step from "pool corruption, tag EXMO" to "this driver is at fault" is inference — and it's the kind of inference the comparison sections below are built to test.
Where the interpretation begins
Reading the blamed module without reading too much
Three fields in the report name the module the analysis points to, and they're three different levels of the same fact. IMAGE_NAME is the file name (extmon.sys). MODULE_NAME is the base name without extension (extmon). SYMBOL_NAME is the most specific: module, function, and offset (extmon!ExtIoControl+1a4) — provided symbols resolved. If you see only an offset or a question mark where the function should be, the module attribution still stands, but the function-level detail doesn't, and the conclusion should be weaker to match.
On "Probably caused by": that final line is WinDbg's heuristic ranking of the modules in the stack — its best guess at involvement, produced automatically. It is a suspect list, not a finding. The module executing the faulting instruction is often the one that read bad data; the component that wrote it may not appear in the dump at all. The working rule here is simpler: record it, rank it, test it — don't retire the investigation on it.
The reference below lists the fields worth recording from a report, grouped by what they tell you. Filter by group, or scan for a specific field when you're working a dump.
15 fields
BUGCHECK_CODEbug checkThe numeric bug check (e.g. 0xd1) — the headline classification of the crash.
Use it to: name the fault class and drive cross-dump comparison.
BUGCHECK_STRbug checkA short mnemonic for the code (AVDRV for 0xd1).
Use it to: give the crash a handle in your notes.
BUGCHECK_P1–P4bug checkParameters; meaning is code-specific (addresses, IRQL, read/write, pool tags).
Use it to: add structured detail — pool tags especially carry allocator identity.
DEFAULT_BUCKET_IDbug checkMicrosoft's classification label for the crash family.
Use it to: group related crashes when the codes differ slightly.
IMAGE_NAMEmoduleThe file name of the implicated module (extmon.sys).
Use it to: identify and look up the component or vendor.
MODULE_NAMEmoduleThe base name without extension (extmon).
Use it to: reference the module compactly in comparisons.
SYMBOL_NAMEmoduleModule!function+offset when symbols resolved (extmon!ExtIoControl+1a4).
Use it to: the primary correlation key across dumps — if present.
FAULTING_MODULEmoduleThe full module line, including base address and size.
Use it to: confirm the module build you're investigating matches.
CODE_LOCATIONlocationThe function and offset of the faulting instruction.
Use it to: see where inside the module the crash landed.
STACK_TEXTlocationThe kernel stack at the crash: return addresses, innermost first.
Use it to: find the kernel/driver boundary and check the shape of the path.
CURRENT_IRQLcontextThe interrupt level when the crash occurred (0 passive, 2 dispatch, …).
Use it to: high IRQL means fewer operations were legal — the context for codes like 0xd1.
PROCESS_NAMEcontextThe process that was running (System, svchost.exe, …).
Use it to: connect the crash to a workload — System often means a driver path.
THREAD / PROCESScontextKernel addresses of the crashed thread and process.
Use it to: feed !thread / !process for deeper context in a larger dump.
Probably caused byanalysisThe debugger's heuristic ranking of the stack — a suspect, not a verdict.
Use it to: set your first hypothesis, then test it against the other evidence.
FollowupanalysisMicrosoft's internal handling hint (MachineOwner, Reset, Re…).
Use it to: almost nothing diagnostic — it's a routing label, not evidence.
The shape of the crash
Reading the stack without reading a novel
STACK_TEXT is the kernel stack at the moment of the crash: a list of return addresses, innermost first — the sequence of calls that was active when the fault hit. You don't need to read every frame. For driver-crash work, the stack answers two practical questions: which module was executing when it happened, and what kind of path it was on.
The layout to recognize: a driver crash typically shows one or two frames in the driver's code sitting directly on top of kernel frames in nt (ntoskrnl) — a user request or interrupt entered the kernel, the kernel called into the driver, and the fault happened inside that call. That shape is exactly what Probably caused by is picking up. If instead the top frames are all kernel code, the crash landed in the OS's own path — which is the ntoskrnl situation from the next section, and a different investigative question.
k
Prints the kernel stack for the crashed thread — usually cleaner than the report's excerpt.
kb
Adds arguments per frame — occasionally the address in an argument is the bad one, matching a parameter like Arg1 on a 0xd1.
Two cautions. First, CURRENT_IRQL sets the rules: at dispatch level (2) or above, the code is servicing an interrupt, and operations like touching pageable memory are illegal — which is precisely what a 0xd1 reports. A stack that looks innocent can still be fatal if it did an illegal operation at a high IRQL. Second, and more important: the stack shows where the crash landed, not where bad data started. A corrupted pointer can pass through several perfectly clean functions before someone dereferences it — the frames between the writer and the crash site may be entirely innocent, and the guilty component may not be on the stack at all. That's the core of the next section.
The central trap
Why the driver in the dump isn't always the cause
This is the section the whole guide is built around, so it's worth stating plainly: the module executing the faulting instruction is a witness to the crash, not a confession. A driver can be named in the dump because it was the component that read a value another component had corrupted — or because the corruption came from hardware that no driver "owns". Finding the alarm at the fire scene doesn't tell you what started the fire.
The ntoskrnl case
When Probably caused by names ntoskrnl, the instinct is to suspect Windows itself. The accurate read is different: ntoskrnl is the kernel, and kernel-mode stacks almost always contain kernel frames, so the kernel shows up in nearly every crash. A blame on ntoskrnl usually means a kernel routine hit bad data that some other component supplied — a pointer a driver passed in, a structure a driver left corrupt. "The kernel crashed" and "the kernel is the cause" are different statements, and the first is not evidence for the second. Replacing or reinstalling Windows on the strength of an ntoskrnl blame is the classic dead end; the investigation should look for the supplier instead.
Corruption in transit
Memory is shared. A misbehaving driver — or a failing stick of RAM — can corrupt a structure that a completely different, perfectly innocent driver dereferences later. The innocent driver appears in SYMBOL_NAME; the guilty component may never appear in the dump. This is why "same code, different modules across dumps" is one of the most informative patterns you can find: it argues against any single driver being the cause and toward a shared substrate — memory, power, or a common dependency. Pool tags are the tool for this case: when a 0x1a carries the same tag across crashes, the tag identifies the allocating component even when the crashing module changes.
Hardware in disguise
Unstable RAM, marginal power delivery, or an overheating CPU can produce crashes that look exactly like driver faults from the dump's perspective — the kernel still lands on some module, the stack still looks plausible. The tells are in the pattern and in the hardware log: random modules, shifting codes, crashes tied to load or heat, and WHEA-Logger events (or a 0x124 bug check, which is a hardware error report itself). Absence of WHEA events doesn't rule hardware out — it just keeps it as a hypothesis — which is why hardware testing earns its place in the comparison workflow rather than being skipped.
The recurring analytical mistakes, collected in one place so you can check against them:
- Treating "Probably caused by" as a verdict. It's a heuristic ranking. Record it, then test it.
- Analyzing one dump and stopping. One crash supports a hypothesis; a pattern supports a conclusion.
- Blaming ntoskrnl. The kernel is in every stack; look for who supplied the bad data.
- Ignoring missing symbols. An offset-only SYMBOL_NAME is weaker evidence than it looks — say so in the log.
- Skipping the timestamp check. Analyzing a stale dump diagnoses a crash that's already over.
- Reading correlation as causation. A module present in every crash is a suspect to test, not a cause to retire on.
- Running Driver Verifier without a recovery path. On an unstable machine it can make things worse; Safe Mode access first.
- Declaring victory after one clean boot. Confirmation means the specific code staying absent under real use, over days.
From suspect to pattern
Comparing multiple dumps is where the diagnosis happens
A single dump gives you a suspect. The comparison of several dumps gives you a verdict you can defend — or the finding that there is no single suspect, which is itself a diagnosis. The comparison keys are small: bug check code, parameters (especially pool tags), SYMBOL_NAME, and timestamp. Lined up in a table, they usually collapse into one of a handful of recognizable shapes.
| Pattern across dumps | What it suggests | Next move |
|---|---|---|
| Same code, same SYMBOL_NAME every time | Strong signal on that module's code path | Update/rollback test for that driver; targeted Verifier only if a recovery path exists |
| Same code, different modules | Systemic — memory, power, or a shared dependency | Memory test; check 0x1a pool tags; WHEA/thermal review |
| Same module, different codes | That module is involved in several failure modes | Deep-dive the driver: version, vendor notes, symbol availability |
| Different codes, different modules | Noise-like: hardware or deep systemic fault | WHEA check, power/thermal, memory test; consider a larger dump |
| One dump, no recurrence | Not yet evidence | Keep collecting; do not act on a single data point |
One subtlety the table can't carry: a repeated symptom is not automatically a repeated cause. The same code can be produced by different root causes at different times — a driver in week one, a degrading drive in week three — so re-correlate after any change you make. If the code persists after you've fixed the first suspect, treat the persistence as new evidence, not as a refutation.
The timeline
Correlating dumps with Event Viewer and Reliability Monitor
Dumps tell you what happened at the moment of each crash. The event log tells you what happened around it — and "what changed" is the question that separates a driver investigation from a hardware one. Three sources do the work.
Event 1001 (BugCheck) in the System log is the dump's paper twin: the same code and parameters, with a timestamp you can line up against the dump file and against everything else. Kernel-Power event 41 records an unexpected shutdown — and the detail matters: a 41 whose bug check code is 0 usually means the machine stopped without a bug check at all, i.e. a power event rather than a driver fault, which should pull that "crash" out of the driver hypothesis entirely. And WHEA-Logger events (19 and 31) are hardware error records; memory errors in particular often appear in the hours or days before the first visible crash, making them leading indicators rather than coincidences.
reladmin /reliability
Opens Reliability Monitor — the consolidated problem-event timeline, useful for spotting the day the crashes started.
Reliability Monitor is the fastest way to see the shape of the problem: crash times, update installs, and driver installs on one timeline. The investigative payoff is the start date. "Crashes began the day after a driver update" is a claim you can make from dates rather than memory, and it ranks the update above every hypothesis the dump alone could produce.
From pattern to proof
Testing competing explanations
At this point you have a pattern and probably two or three candidate causes. The discipline that separates a diagnosis from a guess is running them as ranked, single-variable tests. List the candidates, order them by how well each fits all the evidence (the dumps, the pool tags, the timeline, the thermal/power context), and test the top one first — with the cheapest test that could distinguish it.
Cheapest-first ordering looks like this: update or roll back the suspect driver (minutes, reversible); run a memory diagnostic (an hour, non-invasive); chase a repeated pool tag to its owning component (hours, no changes to the machine); targeted Driver Verifier (deliberate destabilization — last, and only with a recovery path). Each test has a predicted outcome: if driver X is the cause, its rollback stops code Y within a day or two of normal use. A negative result isn't a waste — it's evidence that rules a hypothesis out, and the next candidate moves up.
And the confirmation standard: the specific bug check stays absent under real use, over days, not a single clean boot. "It hasn't crashed since the rollback" is a working confirmation; "it hasn't crashed since the rollback and I've been running the workload that used to trigger it for a week" is a diagnosis you can write down.
The deliberate stress test
When Driver Verifier is appropriate — and when it isn't
Driver Verifier is Microsoft's tool for the case where dumps point at a driver but ordinary analysis can't prove it. It works by deliberately exercising drivers with invalid operations — bad pointers, illegal IRQL transitions — so that a driver with a latent bug fails loudly and names itself in the resulting crash. A Verifier-induced crash that names the driver under test is the strongest causal signal short of replacing hardware.
Verifier deliberately destabilizes the system.
It is designed to make bad drivers crash — and on a machine that is already crashing, that can mean immediate crashes or a boot loop. Run it per-driver rather than system-wide, only when you have a specific suspect from dump correlation, and only with a recovery path already confirmed (Safe Mode accessible, or another machine available). Plan the exit before you start it.
The appropriate moment is narrow: you have a same-module pattern across dumps, you've already tried the update/rollback cycle, and the timeline supports the driver. The inappropriate moments are equally clear: no specific suspect (system-wide Verifier on an unknown problem), no recovery path, or a production machine where a crash loop has a real cost and the pattern isn't strong enough to justify it. Enable, run, and — importantly — disable:
verifier /standard /driver extmon.sys
Standard flag set, one driver (swap in your suspect). The machine reboots into verification.
verifier /query
Shows what verification is currently active — check this if a previous run was left on.
verifier /reset
Turns verification off. If the machine won't boot normally, run it from Safe Mode.
If a Verifier run produces a crash, the dump from that crash is worth a full read on its own — it was engineered to implicate the driver under test. If the machine stays stable under Verifier for a meaningful period, that's informative too: the driver tolerates the stress cases, which weakens (without eliminating) the case against it.
Escalation
When a minidump runs out of information
Most of the time a minidump is enough, and escalating is wasted effort — a complete dump of a normal driver crash buys you terabytes of data and a very small increase in answer. But there are recognizable signs that the 320 KB slice has run out: !analyze returns sparse or "unable to read" results, the fault is in a data structure whose contents you need to inspect, the module list looks truncated, or you need to identify which process triggered a kernel path. Those are the cases where switching to a kernel (or, rarely, complete) dump and capturing one clean crash changes what the question can be.
The change itself is a setting: Startup and Failure → Write debugging information → Kernel memory dump, then let the next crash write MEMORY.DMP. Do it deliberately and revert or leave it consciously — it's a bigger disk write per crash, and on a machine that crashes often it adds up. And one scenario where no dump helps: when the system hangs hard or corrupts itself before the dump writer runs. There, the investigation runs on the paper trail — Event 1001, Kernel-Power 41, WHEA records — plus hardware testing, which is why the evidence-map table from earlier matters as much as the debugger does.
The whole loop
A repeatable investigation workflow
Everything above, compressed into the loop you'd actually run on a machine: evidence first, interpretation second, testing third, confirmation last. The diagram shows the shape — a dump feeding analysis, analysis producing suspects that get correlated across crashes, and only then a tested conclusion.
As steps, the loop is eight moves:
- Verify the evidence. Dumps exist, timestamps match the crashes, Event 1001 agrees with the files.
- Prepare the tool. WinDbg installed, symbol server set, symbol loading confirmed with lmvm.
- Analyze each dump. !analyze -v per file; record code, parameters, module fields, and symbol status.
- Build the pattern table. One row per crash: time, code, parameters, SYMBOL_NAME, what changed that day.
- Correlate the timeline. Crash dates against updates, driver installs, WHEA events, and your own changes.
- Rank the hypotheses. Two or three candidates, ordered by fit with all the evidence.
- Test the top one. Cheapest discriminating test first; one variable at a time; record negative results.
- Confirm over real use — then document. The specific code stays absent for days; escalate (larger dump, Verifier, hardware) only when the pattern says to.
The checklist below is the same loop as tickable items — the investigation log, in short form. Your ticks are saved in this browser.
What does your pattern look like?
Select the pattern that fits your dumps.
FAQ
Minidump questions, answered
Where are BSOD minidumps saved?
Minidump files are saved in C:\Windows\Minidump as timestamped .dmp files. When the dump type is Automatic or Kernel, Windows instead writes a larger MEMORY.DMP file to the root of the system drive.
My Minidump folder is empty — are dumps disabled?
Not necessarily. With the default Automatic memory dump setting, Windows writes MEMORY.DMP to the drive root rather than to the Minidump folder. Check the debugging-information setting under Startup and Failure, and check for MEMORY.DMP before concluding that no dump exists.
What does "Probably caused by" actually mean in WinDbg?
It is WinDbg's automated heuristic: the debugger ranks the modules in the stack and names the one it considers most likely involved. It is a useful starting suspect, not a confirmed cause — the module executing the faulting instruction can be the victim of corruption written elsewhere.
The dump blames ntoskrnl.exe — is the kernel broken?
Almost never. ntoskrnl.exe is the kernel itself and appears in nearly every kernel-mode stack. A blame on ntoskrnl usually means a kernel routine hit bad data that some other component supplied; the investigation should look for the supplier, not replace the OS.
Do I have to install WinDbg to read a dump?
WinDbg (from the Debugging Tools for Windows, available with the Windows SDK) is the standard free tool from Microsoft. There is no built-in viewer that provides the same analysis depth, so installing the tools once is the normal preparation step.
Can a crash dump be wrong?
The raw state recorded in a dump is reliable, but automated interpretation can misattribute it: a module named in the analysis is where the crash landed, not necessarily what started it. Correlation across multiple dumps and with other evidence is what turns a suspect into a conclusion.
How many dumps do I need before I can trust a conclusion?
There is no fixed number, but one dump rarely supports a cause. Three or more crashes with the same bug check code and the same SYMBOL_NAME is a strong pattern; the same code with different modules argues against a single-driver cause and points toward memory, power, or a systemic problem.
Is Driver Verifier safe to run?
Driver Verifier deliberately stresses drivers to expose faulty behavior, so it can cause immediate crashes — and on a machine already in a crash loop, even a boot loop. Use it per-driver rather than system-wide, only when you have a specific suspect and a recovery path such as Safe Mode, and plan to disable it with verifier /reset.