What Happens Without a Base Case in C Recursion
When a recursive function in the C programming language fails to establish a valid base case, the function triggers unbounded self-invocation, leading to rapid call stack exhaustion and an immediate program crash known as a segmentation fault. This article breaks down the mechanics of recursion in C, explains how memory allocation behaves during infinite recursion, details the resulting stack overflow, and outlines how the operating system terminates the faulty process.
The Function Call Stack and Stack Frames
In C, execution state and memory for function execution are managed using a region of memory known as the call stack. Every time a function is invoked, the program allocates a dedicated block of memory on this stack called a stack frame (or activation record). A single stack frame contains:
- The function's parameters and arguments.
- All locally declared variables.
- CPU register states saved for context switching.
- The return address pointing to the instruction that must execute once the function finishes.
When a function finishes its execution, its stack frame is popped from the stack, freeing that memory back to the system and returning control to the caller.
The Consequence of a Missing Base Case
A recursive function relies on a base case—a conditional check such
as an if statement—to stop making further recursive calls
and begin unwinding the stack.
Without a valid base case, or if the base case condition is logically unreachable, the function enters an infinite loop of recursive calls. With every call:
- The current execution state is suspended.
- A new stack frame is allocated directly adjacent to the previous one on the stack.
- No stack frames are ever released or popped because no single call can ever run to completion.
Stack Overflow
The call stack allocated to a process by the operating system is
strictly finite. On most modern systems, the default stack size ranges
from 1 MB to 8 MB depending on the compiler and operating system limits
(such as ulimit -s on Linux).
Because memory is added to the stack with each recursive step, the stack pointer continuously shifts toward the boundary of the allocated stack segment. When the function continues calling itself, the stack memory is entirely consumed in a fraction of a second. This condition is known as a stack overflow.
Operating System Intervention and Segmentation Fault
Once the stack overflows, the program attempts to write memory outside the designated bounds of the process's stack segment:
- Memory Protection Violation: Modern operating systems employ memory management units (MMUs) with virtual memory protection. When a function attempts to write a new stack frame into a memory page that is not mapped or does not belong to the program's writable memory, the hardware triggers a page fault.
- Signal Dispatch: The operating system recognizes
that this memory access is illegal. On Unix-like systems (Linux, macOS),
the kernel dispatches the
SIGSEGV(Signal 11) signal to the process. On Windows, anEXCEPTION_STACK_OVERFLOWor access violation exception is raised. - Process Abort: Unless explicitly caught (which is
rarely possible or advisable for stack exhaustion), the signal causes
the operating system to immediately terminate the process to prevent
corruption of adjacent memory. The user typically sees the error
message:
Segmentation fault (core dumped).
To prevent this fatal failure, every recursive algorithm in C must guarantee that every possible execution path eventually converges toward a valid, terminating base condition before stack limits are reached.