Rust - Is the stack size different for debug vs. release mode?

Viewed 415

Consider the following program:

fn recursive_call(x: u32) -> u32 {
    println!("x: {:?}", x);
    recursive_call(x +1)
}

fn main() {
    recursive_call(0);
}

When I run cargo build && ./target/debug/recursive_call, this crashes after x: 58152:

x: 58152

thread 'main' has overflowed its stack
fatal runtime error: stack overflow
Aborted (core dumped)

while when I run cargo build --release && ./target/release/recursive_call, this crashes only after x: 104728:

x: 104728

thread 'main' has overflowed its stack
[...]

I wondering where this difference in behavior comes from? Is the stack size different in release vs. debug mode? Or is this because of some compile time optimizations I am missing (if so, what would so optimizations be?)

2 Answers

Yep, according to Godbolt on x86-64 the reserved stacksize for the function in debug mode is 120 bytes, with optimizations turned on (-O) it is 72 bytes. That is quite normal.

The stack size is the same for debug and release (and unless you have threads, the stack size is actually fixed by the OS, see eg. ulimit -s on Linux). However the stack usage may be different because in debug mode the compiler adds some data to each stack frame to help debuggers find local variables.

Note that tail-call optimization may cause the compiler to remove the recursion and allow an infinite loop in release mode.

Related