堆栈溢出错误或异常?

Ant*_*Ant 10 c++ recursion

为什么以下结果没有错误?

void func()
{
   func();
}

int main()
{
   func();
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*lia 23

理论上,它会溢出堆栈(因为,即使没有使用局部变量,每次调用都会在堆栈上添加先前的返回地址); 实际上,在启用优化的情况下,它不会因为尾调用优化而溢出,这实际上避免了任何资源消耗在跳转中转换调用,因此不会消耗堆栈.

通过检查 OP代码生成的优化程序集,可以很容易地看出这一点:

func():
.L2:
        jmp     .L2
main:
.L4:
        jmp     .L4
Run Code Online (Sandbox Code Playgroud)

func被优化为无限循环,无论是"独立版本"还是内联调用main.

请注意,这与"as if"规则的C++标准一致:编译的程序必须在代码中请求的那样运行(就效果而言),并且由于堆栈大小只是一个实现限制,生成的代码使用a call和使用a的代码jmp是等价的.

但是:这是一个更特殊的情况,因为标准甚至说无限循环(定义为 "不终止且没有一些副作用")实际上是未定义的行为,因此理论上编译器将被允许省略该调用完全.


Pup*_*ppy 8

可能,您的编译器对其进行了优化并将其转换为while(true){}构造.


thk*_*ala 5

确实以我的Linux系统上的Segmentation故障结束- Valgrind指示可能的堆栈溢出,这当然是正确的,因为对于每个函数调用,需要一个新的堆栈帧.

但是,在编译器中启用优化会将整个程序减少到无限循环,这自然不会结束:

        .file   "so.c"
        .text
        .p2align 4,,15
.globl func
        .type   func, @function
func:
.LFB0:
        .cfi_startproc
        .p2align 4,,10
        .p2align 3
.L2:
        jmp     .L2
        .cfi_endproc
.LFE0:
        .size   func, .-func
        .p2align 4,,15
.globl main
        .type   main, @function
main:
.LFB1:
        .cfi_startproc
        .p2align 4,,10
        .p2align 3
.L5:
        jmp     .L5
        .cfi_endproc
.LFE1:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.3"
        .section        .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)

这是有趣的部分:

.L5:
        jmp     .L5
Run Code Online (Sandbox Code Playgroud)