The article explains why making the entire stack out of guard pages is problematic, as it could lead to unbounded memory allocation and system hangs. Instead, fixed guard pages are preferred for bounded fault handling.
<p>In my earlier overview of <a title="How do compilers ensure that large stack allocations do not skip over the guard page?" href="https://devblogs.microsoft.com/oldnewthing/20260311-00/?p=112134"> how compilers on different architectures perform stack probes</a>, <a href="https://devblogs.microsoft.com/oldnewthing/20260311-00/?p=112134&commentid=143919#comment-143919"> Cole Tobin asked</a>, “Why not have a page fault handler that detects the faulting address being the stack and page in the other pages?”</p>
<p><a href="https://devblogs.microsoft.com/oldnewthing/20260311-00/?p=112134&commentid=143920#comment-143920"> Csaba Varga replied</a>, “My guess: you don’t want an invalid pointer dereference to allocate a huge chunk of stack, just because the pointer happens to be pointing where the stack might grow, eventually. You want an invalid pointer dereference to segfault most of the time.”</p>
<p>I agree with Csaba on this.</p>
<p>If the entire stack were made of guard pages, then it means that a single page fault far below the stack limit could take arbitrary long and allocate arbitrarily large quantities of memory. The program might have said that it wants stacks to default to 1GB, and now a single page fault on the stack could result in a long pause as the system allocates 1GB of memory. If you study the problem in the debugger, what you see is that a single memory read takes several minutes.</p>
<p>And even worse is that there’s no way to stop it, since it’s happening in kernel mode. You see a program starting to balloon and consume all the memory in the system, so you go to Task Manager and terminate it, but the process doesn’t die. It just keeps on growing!</p>
<p>Even if the guard page is more than one page, it’s still a small fixed number of pages, the system can satisfy a guard page fault in a short amount of time. And more importantly, the amount of work is bounded.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20260713-00/?p=112528">Why don’t we just make the entire stack out of guard pages?</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
# Why don't we just make the entire stack out of guard pages? - The Old New Thing
Source: [https://devblogs.microsoft.com/oldnewthing/20260713-00?p=112528](https://devblogs.microsoft.com/oldnewthing/20260713-00?p=112528)
In my earlier overview of[how compilers on different architectures perform stack probes](https://devblogs.microsoft.com/oldnewthing/20260311-00/?p=112134),[Cole Tobin asked](https://devblogs.microsoft.com/oldnewthing/20260311-00/?p=112134&commentid=143919#comment-143919), “Why not have a page fault handler that detects the faulting address being the stack and page in the other pages?”
[Csaba Varga replied](https://devblogs.microsoft.com/oldnewthing/20260311-00/?p=112134&commentid=143920#comment-143920), “My guess: you don’t want an invalid pointer dereference to allocate a huge chunk of stack, just because the pointer happens to be pointing where the stack might grow, eventually\. You want an invalid pointer dereference to segfault most of the time\.”
I agree with Csaba on this\.
If the entire stack were made of guard pages, then it means that a single page fault far below the stack limit could take arbitrary long and allocate arbitrarily large quantities of memory\. The program might have said that it wants stacks to default to 1GB, and now a single page fault on the stack could result in a long pause as the system allocates 1GB of memory\. If you study the problem in the debugger, what you see is that a single memory read takes several minutes\.
And even worse is that there’s no way to stop it, since it’s happening in kernel mode\. You see a program starting to balloon and consume all the memory in the system, so you go to Task Manager and terminate it, but the process doesn’t die\. It just keeps on growing\!
Even if the guard page is more than one page, it’s still a small fixed number of pages, the system can satisfy a guard page fault in a short amount of time\. And more importantly, the amount of work is bounded\.
### Category
### Topics
## Author

Raymond has been involved in the evolution of Windows for more than 30 years\. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie\-jeebies\. The Web site spawned a book, coincidentally also titled The Old New Thing \(Addison Wesley 2007\)\. He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information\.
Raymond Chen follows up on his previous article about stack limit checking on ARM64, addressing a detail about the unconventional use of the x15 register in stack probe functions and comparing register usage across multiple architectures.
This article discusses a fundamental memory safety challenge involving tagged unions where a pointer to one variant is used after the union is overwritten with a different variant, leading to type confusion. The author also argues that buffer overflows are the most exploitable memory error and could have been mitigated with better array syntax.
The article explains how to use unsafe pointer arithmetic in Go to eliminate bound checks that the compiler cannot remove, improving performance in hot paths. It discusses the overhead of bound checks and conventional BCE before introducing the unsafe approach.
A developer shares an experience where OpenAI's Codex added an excessive guard rail by inserting a runtime extension existence check into an API, which a human engineer would never do.
The article explains how the alloca function allocates memory on the stack by calling the __chkstk function to probe the stack before adjusting the stack pointer, demonstrated with x86-64 assembly code.