EmbeddedRelated.com

Stack Overflow

Category: Rtos | Also known as: stack overflows

A stack overflow occurs when a program writes beyond the allocated bounds of its call stack, typically by consuming more stack space than was reserved. In embedded and RTOS contexts this most commonly results from deep call chains, excessive local variable allocation, or unbounded recursion, and it can silently corrupt adjacent memory rather than producing an immediate, obvious fault.

In practice

Sizing stacks correctly at the start of a project is difficult because the full call graph, including library code and printf-family functions, is rarely obvious. A practical approach is to start with a conservatively large stack, profile high-water marks in realistic test runs, then reduce stack sizes incrementally. The blog post "Are We Shooting Ourselves in the Foot with Stack Overflow?" discusses how teams often underestimate this risk in production firmware. Interrupt service routines deserve special attention: on Cortex-M cores the hardware always uses the MSP (Main Stack Pointer) for exceptions, regardless of RTOS presence; RTOSes typically configure thread mode to use the PSP (Process Stack Pointer) while leaving MSP for exceptions and interrupts, so ISR stack usage must be accounted for separately.

Discussed on EmbeddedRelated

Frequently asked

Why does a stack overflow often cause a crash far from the actual overflowing function?
The overflow corrupts memory adjacent to the stack, but the corrupted data may not be read until much later, when another task accesses its stack, a return address is popped, or a global variable is dereferenced. By the time the fault surfaces, the original overflowing call frame has long since been unwound, making the call stack at the point of crash largely unrelated to the root cause.
How does FreeRTOS stack overflow detection work, and what are its limits?
FreeRTOS offers two configurable detection modes (configCHECK_FOR_STACK_OVERFLOW). Mode 1 checks whether the stack pointer is within the allocated range at each context switch. Mode 2 additionally checks whether a pattern written into the stack at task creation has been disturbed. The exact checks performed vary by port and configuration. Both modes only run at context-switch boundaries, so a transient overflow that resolves before the next switch may go undetected. Neither mode replaces MPU-based guard regions for catching overflows the moment they occur.
Can enabling an MPU guard region fully prevent stack overflow damage?
A guard region at the bottom of each task stack will typically trigger a MemManage fault or escalate to a HardFault the first time code writes into that region, catching the overflow immediately rather than silently. However, the exact fault raised depends on the core, fault configuration, and system state. The guard region itself must be sized and aligned to the MPU's region constraints for the specific core and implementation to be effective, and it stops damage only to memory below the guard. Memory above the stack that is overflowed from the opposite direction is not protected by this scheme.
What GCC options help estimate stack usage at compile time?
Compiling with -fstack-usage causes GCC to emit a .su file for each translation unit listing the stack frame size of every function, annotated as static, dynamic, or dynamic,bounded. The -Wstack-usage=N flag warns when any single frame exceeds N bytes. These figures cover only statically analyzable frames; calls through function pointers and unbounded recursion still require manual analysis or runtime measurement.
Is stack overflow the same as a buffer overflow?
They overlap but are not identical. A stack overflow specifically means the stack has exhausted or exceeded its allocated region (whether or not the stack pointer has crossed a hard boundary). A buffer overflow is a broader term for writing past the end of any buffer, which may be on the stack, the heap, or in static storage. A stack-allocated array written past its bounds is both a buffer overflow and a potential contributor to a stack overflow, but the terms describe different failure modes.

Differentiators vs similar concepts

Stack overflow is sometimes conflated with heap overflow (writing past a heap allocation) or with a general buffer overflow. The key distinction is that stack overflow refers specifically to exhausting or exceeding the call stack region, whereas heap overflow involves the dynamically allocated memory region. The two regions typically grow toward each other in classic single-stack bare-metal layouts, so a severe stack overflow can collide with the heap and vice versa, but their causes and detection strategies differ.