1

考虑以下程序:

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

fn main() {
    recursive_call(0);
}

当我运行时cargo build && ./target/debug/recursive_call,这会在以下情况下崩溃x: 58152

x: 58152

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

而当我跑步时 cargo build --release && ./target/release/recursive_call,这只会在以下情况下崩溃x: 104728

x: 104728

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

我想知道这种行为差异来自哪里?发布与调试模式的堆栈大小是否不同?或者这是因为我缺少一些编译时优化(如果是这样,那么优化是什么?)

4

2 回答 2

2

是的,根据x86-64 上的 Godbolt,在调试模式下为函数保留的堆栈大小是 120 字节,启用优化 ( -O) 它是 72 字节。这是很正常的。

于 2021-01-25T15:18:05.323 回答
0

调试和发布的堆栈大小相同(除非您有线程,否则堆栈大小实际上由操作系统固定,例如ulimit -s在 Linux 上参见)。然而,堆栈的使用可能会有所不同,因为在调试模式下,编译器会向每个堆栈帧添加一些数据以帮助调试器找到局部变量。

请注意,尾调用优化可能会导致编译器删除递归并在发布模式下允许无限循环。

于 2021-01-26T08:42:18.563 回答