HN Debrief

How do functions like alloca allocate memory from the stack?

  • Programming
  • Security
  • Infrastructure
  • Developer Tools

The post is a low-level walkthrough of how functions like `alloca` appear to allocate memory “from the stack” even though the stack is not a heap. The key idea is that `alloca` is really compiler or assembly support that adjusts the stack pointer inside a function, then relies on normal function exit to discard that memory. Chen focuses on the Windows wrinkle that large stack growth must be probed page by page so execution cannot skip over the stack’s guard page. That is what helpers like `_chkstk` are for.

If your code uses dynamic stack allocation, audit it now for stack probing and bounded sizes, especially on Windows and with GCC or Clang settings that affect stack-clash protection. More broadly, treat stack allocation as an ABI and compiler feature, not a cute library trick, because portability and security depend on code generation details.

Discussion mood

Mostly technical and mildly wary. People liked the explanation, but the dominant mood was that `alloca` is a sharp tool whose correctness and security depend on compiler and OS details that many programmers underestimate.

Key insights

  1. 01

    VLA versus alloca is really a tooling choice

    Variable-length arrays solve several problems that `alloca` leaves hanging. They have block scope, carry the actual dynamic size in the type system, and can reduce stack waste compared with fixed worst-case buffers. That makes them the cleaner model in C when the compiler supports them well. The catch is that support is uneven, especially around MSVC, so the argument is less about language purity than about whether your toolchain can enforce safe limits and generate the right probes.

    If you ship portable C across multiple compilers, decide explicitly whether VLA support is part of your baseline. If it is not, ban both VLAs and `alloca` in shared code and provide a single bounded-buffer pattern instead.

      Attribution:
    • uecker #1 #2
    • rurban #1
  2. 02

    alloca lives outside standard C

    `alloca` only makes sense when the compiler or handwritten assembly can manipulate the stack pointer in a calling-convention-aware way. That means it is better understood as a compiler built-in or ABI service than as a library function, even if the syntax makes it look ordinary. This framing explains why it has survived for decades without becoming a clean portable feature.

    When reviewing code that uses `alloca`, inspect generated assembly or compiler docs, not just headers. Treat it like inline assembly with nicer syntax.

      Attribution:
    • pjmlp #1
  3. 03

    Small nested frames still probe the stack

    The guard-page problem is less mysterious once you remember that a call instruction usually writes a return address to the stack. That write counts as touching the newly descended page, and typical prologue code then pushes more state. So multiple sub-4 KB frames do not normally bypass probing one page at a time. Tail-call optimization is the interesting exception because it can avoid creating a fresh frame at all.

    If you are reasoning about stack safety from source alone, include call and prologue side effects in the model. Optimizations like tail calls can change that model, so verify behavior in optimized builds.

      Attribution:
    • stkdump #1 #2
    • st_goliath #1
  4. 04

    Linux relies on compiler mitigation too

    Windows is not unusual in needing help to grow the stack safely. Linux can grow stack mappings downward, but that alone does not prevent Stack Clash style jumps over guard pages. The meaningful protection comes from compiler-generated page probing such as GCC’s `-fstack-clash-protection`, not from assuming the kernel will always catch unsafe growth.

    Do not assume the operating system makes large stack allocations safe by itself. Make stack-clash protection an explicit build setting and confirm it is enabled in production toolchains.

      Attribution:
    • rramadass #1 #2
    • Joker_vD #1
    • inigyou #1
  5. 05

    Arena allocation is the portable fallback

    If you want the convenience of temporary allocations without depending on `alloca` or VLA support, a dedicated arena gives you the same broad usage pattern with predictable portability. You lose automatic cleanup at block exit, but you gain a model that works consistently across compilers and languages. That is a better trade when you need dynamic scratch space in shared infrastructure code.

    For cross-platform libraries, prefer an explicit scratch arena over ad hoc dynamic stack allocation. It centralizes limits, cleanup, and failure handling instead of hiding them in compiler-specific behavior.

      Attribution:
    • OCTAGRAM #1

Against the grain

  1. 01

    Maybe writable data should leave the stack

    One line of thought pushed past guard pages and asked why ordinary writable data lives on the same stack as return addresses at all. A split design with separate control and data stacks would shrink stack-smashing risk and reduce pressure on stack-growth defenses. That is far outside mainstream C ABIs today, but it reframes the problem as an architectural compromise rather than an unavoidable fact of life.

    If you work on runtimes, kernels, or hardened systems, look at split-stack and shadow-stack designs instead of only adding more probes and canaries. The biggest security gains may come from changing where data is allowed to live.

      Attribution:
    • Joker_vD #1
    • rramadass #1
  2. 02

    Windows internals still attract developers

    Against the gloom about disappearing low-level Windows expertise, several comments said the platform remains compelling precisely because it rewards digging. The opaque parts create room for investigation, and the tooling stack for profiling, debugging, and performance work was described as unusually strong. That suggests the talent problem is not pure lack of interest. It may be more about incentives and where the work is available.

    If you need systems talent, do not assume nobody wants this work. Make the role legible, give people serious tools, and present the debugging and performance angle as a craft worth mastering.

      Attribution:
    • delta_p_delta_x #1 #2
    • stelonix #1

In plain english

-fstack-clash-protection
A GCC compiler option that generates code to probe stack growth and reduce stack clash vulnerabilities.
-Wvla-larger-than
A GCC warning option that flags variable-length arrays larger than a chosen bound.
_chkstk
A Windows helper routine that touches stack memory page by page when a function needs a large stack frame, so guard pages are triggered safely.
ABI
Application Binary Interface, the low-level calling convention and data representation rules used when compiled code interacts at runtime.
alloca
A nonstandard function or compiler built-in that allocates temporary memory by moving the current function’s stack pointer.
GCC
GNU Compiler Collection, a major open-source compiler suite for C, C++, and other languages.
guard page
A protected memory page placed next to the current stack allocation so the operating system notices when the stack grows into it.
MSVC
Microsoft Visual C++, Microsoft's C and C++ compiler and development toolchain.
stack clash
A class of security bugs where a large stack growth skips over a guard page and lands in other mapped memory.
tail-call optimization
A compiler optimization that turns a function call in return position into a jump, avoiding creation of a new stack frame.
VLA
Variable-length array, a C feature that lets an array on the stack have a size decided at runtime.

Reference links

Related stack and memory writeups

Learning resources on low-level and graphics programming

Organizational and industry context