是否有一种语言可以启用一种机制,当超出原始堆栈空间时在堆上分配新的堆栈空间?
我记得在我的大学里做过一个实验室,在那里我们用C语言进行内联汇编来实现基于堆的可扩展堆栈,因此我知道原则上应该可行。
我了解开发应用程序时出现堆栈溢出错误可能很有用,因为它会迅速终止疯狂的无限递归而不会使您的系统占用大量内存并开始交换。
但是,当您要部署完成且经过测试的应用程序并且希望它尽可能强大时(例如,这是在台式计算机上运行的非常关键的程序),很高兴知道它不会在堆栈受限制的某些其他系统上,某些对象占用更多空间或程序遇到比测试中需要更多堆栈内存的非常特殊的情况时,该应用程序将失败。
我认为正是由于这些陷阱,生产代码中通常避免了递归。但是,如果我们有一种在生产代码中自动堆栈扩展的机制,那么我们将能够使用递归编写更优雅的程序,因为它知道当系统有16 GB的可用堆内存时不会出现意外的段错误...
有先例。
用于Haskell编译器的GHC的运行时使用堆而不是堆栈。仅当您调用外来代码时才使用该堆栈。
Google的Go实施将分段堆栈用于goroutine,可根据需要扩大堆栈。
Mozilla的Rust曾经使用分段堆栈,尽管它决定导致的问题多于解决的问题(请参阅[rust-dev]在Rust中放弃分段堆栈)。
如果提供内存,则某些Scheme实现会将堆栈帧放在堆上,然后像其他对象一样对这些帧进行垃圾回收。
在传统的命令式语言编程风格中,大多数代码将避免递归调用自身。堆栈溢出很少在野外看到,它们通常是由草率的编程或恶意输入触发的,尤其是递归下降解析器等,这就是为什么当嵌套超过阈值时某些解析器会拒绝代码的原因。
避免生产代码中堆栈溢出的传统建议:
不要编写递归代码。(示例:重写搜索算法以使用显式堆栈。)
如果您确实编写了递归代码,请证明递归是有界的。(示例:搜索平衡树以树的大小的对数为界。)
如果您无法证明它是无界的,请为其添加一个边界。(示例:为解析器支持的嵌套数量增加一个限制。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句