Rch*_*ul4 2 c++ stack-overflow iostream mutual-recursion
我正在学习函数,并决定制作一个循环,其中两个函数(在本例中为funcA和funcB)永远相互调用,但一段时间后它将停止执行。代码如下:
#include <iostream>
void funcA(); //forward declaration
//funcB calls funcA
void funcB()
{
funcA();
}
//funcA prints 1 and calls funcB again
void funcA()
{
std::cout<<1;
funcB();
}
//main calls funcB
int main()
{
funcB();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
返回值是-1073741571(0xC00000FD)。你能解释为什么会这样吗?
无论何时调用函数,程序都会保留少量空间来保存该函数的信息(局部变量的空间,有关函数退出后返回何处的信息,等等)。该内存是从称为调用堆栈(或简称为“堆栈”)的区域分配的,当函数完成运行时,它将返回到堆栈。
堆栈通常具有固定的小尺寸。如果调用链很长(通常以成千上万个调用为单位),则可能会耗尽堆栈空间,程序将终止并产生一个错误,称为堆栈溢出。这就是程序中正在发生的事情。
一般而言,如果您具有递归(或相互递归)功能,则需要确保对于“太大”的定义,递归深度不会变得太大。事情可能发生。在某些特殊情况下,某些编译器可以识别出您正在编写递归代码并将其转换为不分配多个堆栈帧的代码(有关更多详细信息,请参见“尾调用消除”),但这是一个例外,而不是规则。
好的,因为这是Windows 10上的gcc,所以请看一下该好螺栓
如果未启用任何优化,则会显式调用这两个函数。
b():
push rbp
mov rbp, rsp
call foo()
call a()
nop
pop rbp
ret
a():
push rbp
mov rbp, rsp
call b()
nop
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
As other answer point out each call leaves on stack information how to come back to function which called function.
Now since functions never return this information is never removed from stack, but is constantly added. As a result you have got stack overflow which on Windows is indicated by value 0xC00000FD.
Now if you enable optimization (-O2) compiler is able to figure out this is infinitive loop (using technique called tail recursion).
b():
sub rsp, 8
.L2:
call foo()
jmp .L2
a():
sub rsp, 8
.L6:
call foo()
jmp .L6
Run Code Online (Sandbox Code Playgroud)
So with optimization enabled you will have infinitive loop as you are expecting.
| 归档时间: |
|
| 查看次数: |
110 次 |
| 最近记录: |