作为一个初学者C ++编程和计算机系统的架构,我还在学习C的基础++。 昨天,我读到递归函数,所以我决定写我自己,这是我写的:(很基本的)
int returnZero(int anyNumber) {
if(anyNumber == 0)
return 0;
else {
anyNumber--;
return returnZero(anyNumber);
}
}
当我这样做:INT ZERO1 = returnZero(4793); 它导致堆栈溢出,但是,如果我传递值4792作为参数,不发生溢出。
任何想法,为什么?
每当你调用一个函数,包括递归,返回地址和经常的参数被压入调用堆栈 。 堆栈是有限的,所以如果递归太深了你会最终运行的堆栈空间。
令我惊讶的是,只需要你的机器上4793次调用使栈溢出。 这是一个非常小的堆栈。 相比较而言,运行在我的电脑上相同的代码需要大约100倍的程序崩溃之前,很多电话。
堆栈的大小进行配置。 在Unix上,命令ulimit -s
。
鉴于该功能是尾递归 ,一些编译器或许能够把它变成一个跳转到优化递归调用了。 一些编译器可能会进一步把你的例子:当问及最大的优化, gcc 4.7.2
转换整个功能分为:
int returnZero(int anyNumber) {
return 0;
}
这需要整整两个安装说明:
_returnZero:
xorl %eax, %eax
ret
很简约。
当你做你的筹码是有限的尺寸等4793
电话你打了极限,而4792
正好进来下。 每个函数调用将使用堆栈的内部管理,也许参数上的部分空间。
本页面给出了一个例子像一个递归函数调用中的堆栈的外观。
你刚才打你的系统调用堆栈的大小限制,这是发生了什么。 出于某种原因,在您的系统堆栈微小的4793所函数调用的深度是相当小的。
我的猜测是你堆是完全足够大,以适应4792项 - 今天。 明天或者下一个,这个数字可能会有所不同。 递归程序可以是危险的,这个例子illistrates原因。 我们尽量不要让递归得到这个深或“坏”的事情都可能发生。
任何“无边”递归,也就是递归调用并非天然局限于一个小的(ISH)多少会有这样的效果。 究竟在何处去限制取决于操作系统,该函数被调用(编译器,该函数调用递归函数,等,等)的环境。
如果再添变数,说int x[10];
给你的函数调用您的递归函数,数需要崩溃就会改变(可能约5左右)。
用不同的编译器编译它(甚至是不同的编译器设置,如优化开启),它可能会再次发生变化。
使用递归,就可以实现SuperDigit:
public class SuperDigit
{
static int sum = 0;
int main()
{
int n = 8596854;
cout<<getSum(n);
}
int getSum(int n){
sum=0;
while (n > 0) {
int rem;
rem = n % 10;
sum = sum + rem;
n = n / 10;
getSum(n);
}
return sum;
}
}