C中的递归深度是不是有任何硬连线限制

Posted

技术标签:

【中文标题】C中的递归深度是不是有任何硬连线限制【英文标题】:Is there any hard-wired limit on recursion depth in CC中的递归深度是否有任何硬连线限制 【发布时间】:2012-05-01 20:08:07 【问题描述】:

正在讨论的程序尝试使用recursion 计算sum-of-first-n-natural-numbers。我知道这可以使用一个简单的公式n*(n+1)/2 来完成,但这里的想法是使用recursion

程序如下:

#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 时,它会导致Segmentation fault (core dumped)

以下内容来自gdb 消息。

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

我的问题:

    C 中的recursion depth 是否有任何硬接线限制?还是recursion depth 取决于可用的堆栈内存?

    程序收到 reSIGSEGV 信号的可能原因有哪些?

【问题讨论】:

两个问题,请发两个问题。问题 1 可能重复 ***.com/q/2630054/1025391 【参考方案1】:

C 中的递归深度没有理论上的限制。唯一的限制是您的实现,通常是有限的堆栈空间。 (请注意,C 标准实际上并不需要基于堆栈的实现。我不知道任何不基于堆栈的实际实现,但请记住这一点。)

SIGSEGV 可能由多种原因引起,但超出堆栈限制是一种相对常见的情况。取消引用坏指针是另一回事。

【讨论】:

【参考方案2】:

通常限制是堆栈的大小。每次调用函数时,都会吃掉一定数量的堆栈(通常取决于函数)。吃掉的量就是栈帧,函数返回时回收。当程序启动时,堆栈大小几乎是固定的,要么是由操作系统指定(并且通常可以在那里调整),要么是在程序中硬编码。

某些实现可能有一种技术,可以在运行时分配新的堆栈段。但总的来说,他们不会。

一些函数会以稍微更不可预测的方式消耗堆栈,例如当它们在那里分配一个可变长度数组时。

某些函数可能被编译为使用尾调用,以保留堆栈空间。有时您可以重写您的函数,以便所有调用(例如对自身的调用)作为它所做的最后一件事发生,并期望您的编译器对其进行优化。

要准确看出每次调用函数需要多少堆栈空间并不是那么容易,这将取决于编译器的优化级别。在您的情况下,一种便宜的方法是在每次调用时打印&amp;nn 可能在堆栈上(特别是因为程序需要获取它的地址——否则它可能在寄存器中),它的连续位置之间的距离将指示堆栈帧的大小。

【讨论】:

“程序启动时堆栈大小几乎是固定的” - 或者创建线程时,对于除第一个线程之外的任何线程。【参考方案3】:

C 标准没有定义函数调用的最小支持深度。如果确实如此,无论如何都很难保证,它会在5.2.4 Environmental limits 部分的某个地方提到它。

【讨论】:

什么文件的第 5.2.4 节?! 如果你把网址加了书签,你能分享一下吗!?谢谢!【参考方案4】:

1)预计栈的消耗会减少,写成尾递归优化。

gcc -O3 prog.c

#include <stdio.h>

unsigned long long int add(unsigned long int n, unsigned long long int sum)
    return (n == 0) ? sum : add(n-1, n+sum); //tail recursion form


int main()
    printf("result : %llu \n", add(1000000, 0));//OK
    return 0;

【讨论】:

以上是关于C中的递归深度是不是有任何硬连线限制的主要内容,如果未能解决你的问题,请参考以下文章

找到最大递归深度

iOS 是不是提供任何功能来检测外部屏幕是“硬连线”电视输出/HDMI 还是“网络”Airplay 显示器/设备?

匿名函数和闭包规避xdebug限制的函数递归深度限制

为啥 Python 有最大递归深度?

处理超出最大递归深度

Firefox、Chrome、Safari、IE 等的 js 递归限制是多少?