堆栈溢出的递归函数引起的(Stack overflow caused by recursive fu

2019-08-22 09:39发布

作为一个初学者C ++编程和计算机系统的架构,我还在学习C的基础++。 昨天,我读到递归函数,所以我决定写我自己,这是我写的:(很基本的)

int returnZero(int anyNumber) {
    if(anyNumber == 0)
        return 0;
    else  {
        anyNumber--;
        return returnZero(anyNumber);
    }

}

当我这样做:INT ZERO1 = returnZero(4793); 它导致堆栈溢出,但是,如果我传递值4792作为参数,不发生溢出。

任何想法,为什么?

Answer 1:

每当你调用一个函数,包括递归,返回地址和经常的参数被压入调用堆栈 。 堆栈是有限的,所以如果递归太深了你会最终运行的堆栈空间。

令我惊讶的是,只需要你的机器上4793次调用使栈溢出。 这是一个非常小的堆栈。 相比较而言,运行在我的电脑上相同的代码需要大约100倍的程序崩溃之前,很多电话。

堆栈的大小进行配置。 在Unix上,命令ulimit -s

鉴于该功能是尾递归 ,一些编译器或许能够把它变成一个跳转到优化递归调用了。 一些编译器可能会进一步把你的例子:当问及最大的优化, gcc 4.7.2转换整个功能分为:

int returnZero(int anyNumber) {
  return 0;
}

这需要整整两个安装说明:

_returnZero:
        xorl    %eax, %eax
        ret

很简约。



Answer 2:

当你做你的筹码是有限的尺寸等4793电话你打了极限,而4792正好进来下。 每个函数调用将使用堆栈的内部管理,也许参数上的部分空间。

本页面给出了一个例子像一个递归函数调用中的堆栈的外观。



Answer 3:

你刚才打你的系统调用堆栈的大小限制,这是发生了什么。 出于某种原因,在您的系统堆栈微小的4793所函数调用的深度是相当小的。



Answer 4:

我的猜测是你堆是完全足够大,以适应4792项 - 今天。 明天或者下一个,这个数字可能会有所不同。 递归程序可以是危险的,这个例子illistrates原因。 我们尽量不要让递归得到这个深或“坏”的事情都可能发生。



Answer 5:

任何“无边”递归,也就是递归调用并非天然局限于一个小的(ISH)多少会有这样的效果。 究竟在何处去限制取决于操作系统,该函数被调用(编译器,该函数调用递归函数,等,等)的环境。

如果再添变数,说int x[10]; 给你的函数调用您的递归函数,数需要崩溃就会改变(可能约5左右)。

用不同的编译器编译它(甚至是不同的编译器设置,如优化开启),它可能会再次发生变化。



Answer 6:

使用递归,就可以实现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;
    }
}


文章来源: Stack overflow caused by recursive function