Bad RAM, one shared DLL, and badmemorylist
TL;DR: Random Windows blue screens with no WHEA errors came from one bad chip on non-ECC DDR4. Identical ILLEGAL_INSTRUCTION crashes in one shared DLL across processes pointed to a bad physical page, MemTest86 confirmed it, and bcdedit /set {badmemory} badmemorylist fenced the pages off.
Two months of random blue screens, each with a different stop code: corrupt PTEs, critical process died, list entry corruption, page faults. Plus a few hard resets with no bugcheck at all. No WHEA errors anywhere.
Two wrong assumptions
- "No WHEA events, so it isn't RAM." Consumer non-ECC memory has no error detection. A flipped bit never reaches WHEA.
- "Crashes come in bursts, not a gradual curve, so it isn't hardware." One bad cell causes a burst the moment a busy page lands on it, and goes quiet when the page moves.
The tell
Three unrelated services crashed with ILLEGAL_INSTRUCTION at the same offset in the same shared DLL, and the DLL on disk hashed clean. Windows maps one physical copy of a DLL's code into every process. If that one frame is bad, every process decodes the same garbage. A reboot moved the page and the crashes stopped.
Confirming it
Windows Memory Diagnostic found errors within the first pass. MemTest86 found 3,278 errors over 4 passes, even at a slow stock speed. Only 12% came from the row-hammer test, so it wasn't a borderline timing issue. 148 bad addresses fell into 16 pages in three clusters, and always the same two bits. That's one chip.
Fencing it off
Windows can refuse to use specific page frame numbers:
bcdedit /set {badmemory} badmemorylist 0x5EF3E0 0x5EF3E1 ...
bcdedit /enum {badmemory}
I padded each cluster to a 16-page block, 48 pages in all, which costs nothing you'd notice. Two things to know:
/setreplaces the whole list. To add pages later, repeat all the old ones.- Write down where the clusters are. If a later crash lands outside them, the chip is getting worse and the list isn't enough. Mine did, two months later, so a new stick is on the list.