据我所知,尾递归函数在最后一步调用自身(如return语句)但是,函数的第一个实例在所有其他实例都被终止之前不会终止,因此我们得到达到多个实例后堆栈溢出。鉴于递归是最后一步,有没有办法在下一个实例期间或之前终止前一个实例?如果实例的唯一目的是调用下一个实例,那么就没有理由将它存在于内存中,对吗?
答案 0 :(得分:2)
是的,一些编译器会优化尾递归,这样就不需要额外的堆栈空间。例如,让我们看看这个示例C函数:
int braindeadrecursion(int n)
{
if (n == 0)
return 1;
return braindeadrecursion(n - 1);
}
这个功能非常简单;它只返回1.没有优化,clang在我的机器上生成的代码如下所示:
_braindeadrecursion:
00 pushq %rbp
01 movq %rsp,%rbp
04 subq $0x10,%rsp
08 movl %edi,0xf8(%rbp)
0b movl 0xf8(%rbp),%eax
0e cmpl $_braindeadrecursion,%eax
11 jne 0x0000001c
13 movl $0x00000001,0xfc(%rbp)
1a jmp 0x0000002e
1c movl 0xf8(%rbp),%eax
1f subl $0x01,%eax
22 movl %eax,%edi
24 callq _braindeadrecursion
29 movl %eax,%ecx
2b movl %ecx,0xfc(%rbp)
2e movl 0xfc(%rbp),%eax
31 addq $0x10,%rsp
35 popq %rbp
36 ret
如您所见,递归调用位于0x24处。现在,让我们尝试更高的优化:
_braindeadrecursion:
00 pushq %rbp
01 movq %rsp,%rbp
04 movl $0x00000001,%eax
09 popq %rbp
0a ret
现在,看看那个 - 根本没有递归!这个例子非常简单,但优化仍然可以在更复杂的尾递归情况下进行。
答案 1 :(得分:1)
或者: - 你可以增加堆栈大小或 - 不要使用递归,而是使用某种循环。