c - 通过在堆上分配堆栈部分来避免堆栈溢出?

标签 c recursion stack stack-overflow heap-memory

有没有一种语言可以在超出原始堆栈空间时启用在堆上分配新堆栈空间的机制?

我记得在我的大学做过一个实验室,我们在 C 中摆弄内联汇编来实现基于堆的可扩展堆栈,所以我知道原则上应该是可能的。

我知道在开发应用程序时遇到堆栈溢出错误可能很有用,因为它可以快速终止疯狂的无限递归,而不会让您的系统占用大量内存并开始交换。

但是,当您有一个经过良好测试的完整应用程序并希望部署时,您希望它尽可能健壮(假设它是一个在台式计算机上运行的非常关键的程序),那么知道它会很高兴在堆栈更有限、某些对象占用更多空间或程序面临需要比测试更多的堆栈内存的非常特殊的情况下,不会在其他一些系统上悲惨地失败。

我认为正是由于这些缺陷,递归通常在生产代码中被避免。但是如果我们在生产代码中有一个自动堆栈扩展的机制,我们就能够使用递归编写更优雅的程序,因为我们知道它不会意外地出现段错误,而系统有 16 GB 的堆内存可供使用...

最佳答案

这是有先例的。

  • Haskell 编译器 GHC 的运行时使用堆而不是堆栈。堆栈仅在您调用外部代码时使用。

  • Google 的 Go 实现对 goroutine 使用分段堆栈,这会根据需要扩大堆栈。

  • Mozilla 的 Rust 曾经使用分段堆栈,尽管它导致的问题多于解决的问题(参见 [rust-dev] Abandoning segmented stacks in Rust )。

  • 如果内存可用,一些 Scheme 实现将堆栈帧放在堆上,然后像其他对象一样对帧进行垃圾回收。

在命令式语言的传统编程风格中,大多数代码都会避免递归调用自身。堆栈溢出在野外很少见,它们通常由草率的编程或恶意输入触发——尤其是递归下降解析器等,这就是为什么一些解析器在嵌套超过阈值时拒绝代码。

在生产代码中避免堆栈溢出的传统建议:

  1. 不要编写递归代码。 (示例:重写搜索算法以使用显式堆栈。)

  2. 如果您编写递归代码,请证明递归是有界的。 (示例:搜索平衡树以树大小的对数为界。)

  3. 如果你不能证明它是无界的,就给它加上一个界。 (示例:对解析器支持的嵌套数量添加限制。)

关于c - 通过在堆上分配堆栈部分来避免堆栈溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21413815/

相关文章:

html - 在 C 中解析 XML 和 HTML 的最佳且有效的方法

c++ - 可以使用 gcc 中的多个对齐属性来保证缓存行分离吗?

c# - 尝试用递归更优雅地解决电话词

java - N-皇后程序,带堆栈

c++ - 结构构造函数问题导致堆栈溢出

Calloc 内部函数

c++ - 将套接字路由到另一个端口

java - Fibonacci(n) 的这个实现是如何工作的? [递归]

c - C中的递归结构定义,错误 "forward declaration"

c++ - 在 for 循环中声明的指向(本地)对象的指针范围