Lesson
The theory โ The Call Stack: Frames, Return Addresses and Overflows
The call stack is a region of memory where each function call gets a frame: here its argument, the return address (where the caller resumes), the caller's saved frame pointer, and its local variables. The stack pointer marks the lowest address in use; a call moves it down by a frame and a return moves it back up. A recursion d calls deep with frames of f bytes needs dยทf bytes of stack.
What each symbol means
d- the depth: frames on the stack at once
f- the bytes in one frame: 12 here, plus 4 per local variable
- Assumes
- A 32-bit machine in the classic C calling convention: 4-byte slots, the stack growing toward lower addresses, arguments passed on the stack, a frame pointer kept in every frame. Real 64-bit conventions pass the first arguments in registers, compilers may leave the frame pointer out, and on ARM a function that calls nothing can keep its return address in a register, so real frames differ in size and layout from these three slots.
Problem solved in full
-
How deep can recursion go? 4 steps
Press fact(11) overflows. The page's stack holds 128 bytes. Microsoft's linker gives a program 1 MB of stack by default; take that as 1 MiB, 1,048,576 bytes, with this page's frames. How deep can fact go? How deep if each call also keeps one 4-byte local? And how much stack does fib(30) need, against how many calls it makes?
-
One frame here is an argument, a return address and a saved frame pointer: 3 ร 4 = 12 bytes. 128 / 12 = 10.67, so ten frames fit, and fact(11) needs 11 ร 12 = 132 bytes. The results table prints the overflow.
-
1,048,576 / 12 = 87,381.33, so 87,381 frames fit: fact could recurse 87,381 levels before the stack runs out, long after its answer has outgrown a 32-bit int, which happens at 13! = 6,227,020,800.
-
With one 4-byte local each frame is 16 bytes, and 1,048,576 / 16 = 65,536 exactly.
-
fib(30)'s longest chain is 30 frames, 30 ร 12 = 360 bytes. Its calls number 2ยทF(31) โ 1, where F(31) = 1,346,269 is the 31st Fibonacci number: 2,692,537 calls.
Answer
87,381 levels, or 65,536 with one local. fib(30) needs 360 bytes of stack for 2,692,537 calls. Depth decides the stack; for fib, the number of calls decides the time.
-
Learning path
How a computer runs a program
References (2)
- The worked problem's stack size: the linker's default reservation: Microsoft Learn, "/STACK (Stack allocations)," C/C++ build reference, updated 23 February 2022.
- The first insight's 1988 example: fingerd's unbounded read into a 512-byte buffer on the stack: Bob Page, "A Report on the Internet Worm." University of Lowell, 7 November 1988 (copy hosted at Toronto Metropolitan University).