Recursion 为什么递归导致的堆栈溢出无法解决?

Recursion 为什么递归导致的堆栈溢出无法解决?,recursion,compiler-construction,operating-system,Recursion,Compiler Construction,Operating System,任何递归都可以修改为具有堆栈结构的迭代函数,那么我为什么要这样做呢?如果答案是避免堆栈溢出,那么计算机怎么会通过递归溢出呢?为什么编译器不在默认情况下或使用附加关键字自动将递归函数放在堆中的堆栈上?我知道堆也是有限的,但它比分配给程序的堆栈大得多。激活记录确实可以被堆分配,但这通常被认为太昂贵了。尽管有一些实现采用了这种方法:例如Stackless Python和SML/NJ 在这些情况下,动机可能是帮助实现延续,而不是“修复”堆栈溢出。根据和,Windows上的最大堆栈大小为1 MiB。你的问

任何递归都可以修改为具有堆栈结构的迭代函数,那么我为什么要这样做呢?如果答案是避免堆栈溢出,那么计算机怎么会通过递归溢出呢?为什么编译器不在默认情况下或使用附加关键字自动将递归函数放在堆中的堆栈上?我知道堆也是有限的,但它比分配给程序的堆栈大得多。

激活记录确实可以被堆分配,但这通常被认为太昂贵了。尽管有一些实现采用了这种方法:例如Stackless Python和SML/NJ

在这些情况下,动机可能是帮助实现延续,而不是“修复”堆栈溢出。

根据和,Windows上的最大堆栈大小为1 MiB。你的问题很有趣。关键字当然是可能的,编译器也能做到。您需要询问编译器制造商,但我想这不是一个非常有趣的特性

缓存会很困难,因为堆栈上有其他局部变量,而递归会在堆上保留变量。信息分散在内存中


一些递归算法可以转化为真正的迭代算法(如的计算),甚至可以转化为封闭形式的表达式(参见示例)。这样,就不需要对递归调用进行簿记。

在迭代过程中,您可以自己跟踪递归状态

您可以比编译器使用非常通用的过程机制(其效率可能会受到各种ABI问题的影响)更高效地完成这项工作


堆栈检查是可能的,但并非在所有系统上都容易,因为并非所有系统都使用固定堆栈或线性地址空间。当然,它也有开销,因为检查被添加到每个递归中。

堆也不是无限的。。。可以作为迭代函数重新编写,但许多递归函数不是尾部递归函数。每个进程在32位计算机上都有4GB的虚拟内存,其中2GB分配给操作系统数据结构。因此,堆栈的大小受到限制,可能会溢出。默认最大堆栈为1。(和VS!=windows)