C中的递归深度有没有硬连线限制

正在讨论的程序尝试使用递归计算第一n个自然数的和.我知道这可以使用一个简单的公式n *(n 1)/ 2,但这里的想法是使用递归.

方案如下:

#include <stdio.h>

unsigned long int add(unsigned long int n)
{
    return (n == 0) ? 0 : n + add(n-1); 
}

int main()
{
    printf("result : %lu \n",add(1000000));
    return 0;
}

该程序在n = 100,000时运行良好,但当n的值增加到1,000,000时,导致分段故障(core dumped)

以下是从gdb消息中获取的.

Program received signal SIGSEGV,Segmentation fault.
0x00000000004004cc in add (n=Cannot access memory at address 0x7fffff7feff8
) at k.c:4

我的问题:

> C中的递归深度有没有硬连线限制?还是递归深度取决于可用的堆栈内存?
>程序会收到reSIGSEGV信号的可能原因是什么?

解决方法

通常这个限制将是栈的大小.每次调用函数时,都会吃掉一定量的堆栈(通常取决于函数).吃饭量是堆栈帧,当函数返回时它被恢复.程序启动时,堆栈大小几乎几乎固定,无论是由操作系统指定(通常可调整),甚至在程序中都被硬编码.

一些实现可能有一种技术,它们可以在运行时分配新的堆栈段.但是一般来说,他们没有.
>一些函数将以稍微更不可预测的方式消耗堆栈,例如在它们分配可变长度数组时.
>某些函数可能被编译为以保留堆栈空间的方式使用尾部调用.有时你可以重写你的函数,这样所有的调用(比如自己)就像最后一件事情一样发生,希望你的编译器能够优化它.

看到每次调用函数需要多少堆栈空间并不容易,它将受制于编译器的优化级别.在你的情况下,这样做的一个便宜方式是每次打电话时都打印出来; n可能在堆栈上(特别是因为程序需要占用地址 – 否则可能在寄存器中),并且它的连续位置之间的距离将指示堆栈帧的大小.

相关文章

对象的传值与返回说起函数,就不免要谈谈函数的参数和返回值...
从实现装饰者模式中思考C++指针和引用的选择最近在看...
关于vtordisp知多少?我相信不少人看到这篇文章,多半是来自...
那些陌生的C++关键字学过程序语言的人相信对关键字并...
命令行下的树形打印最近在处理代码分析问题时,需要将代码的...
虚函数与虚继承寻踪封装、继承、多态是面向对象语言的三大特...