如何处理或避免C++中的堆栈溢出

Ral*_*zky 24 c++ stack-overflow crash error-handling

在C++中,堆栈溢出通常会导致程序无法恢复的崩溃.对于需要非常强大的程序,这是一种不可接受的行为,特别是因为堆栈大小有限.关于如何处理问题的一些问题.

  1. 有没有办法通过一般技术来防止堆栈溢出.(一种可扩展,强大的解决方案,包括处理大量堆栈的外部库等)

  2. 有没有办法处理堆栈溢出,以防它们发生?优选地,堆栈被解开,直到有处理器来处理该类问题.

  3. 有些语言,有可扩展堆栈的线程.这样的东西在C++中是可能的吗?

关于C++行为解决方案的任何其他有用的评论将不胜感激.

Jam*_*lis 24

处理堆栈溢出不是正确的解决方案,相反,您必须确保程序不会溢出堆栈.

不要在堆栈上分配大变量("大"取决于程序).确保任何递归算法在已知最大深度后终止.如果递归算法可能递归未知次数或大量次数,则自己管理递归(通过维护自己动态分配的堆栈)或将递归算法转换为等效迭代算法

必须"非常强大"的程序不会使用"吃掉大量堆栈"的第三方或外部库.


请注意,某些平台会在发生堆栈溢出时通知程序,并允许程序处理错误.例如,在Windows上,抛出异常.但是,此异常不是C++异常,它是异步异常.虽然C++异常只能由throw语句抛出,但在程序执行期间可能会随时抛出异步异常.但是,这是预期的,因为堆栈溢出可能随时发生:任何函数调用或堆栈分配都可能溢出堆栈.

问题是堆栈溢出可能导致异步异常被抛出,即使是不希望抛出任何异常的代码(例如,来自标记的函数noexceptthrow()在C++中).因此,即使您以某种方式处理此异常,也无法知道您的程序处于安全状态.因此,处理异步异常的最佳方法是根本不处理它(*).如果抛出一个,则表示程序包含错误.

其他平台可能有类似的方法来"处理"堆栈溢出错误,但任何此类方法都可能遇到同样的问题:预期不会导致错误的代码可能会导致错误.

(*)有一些非常罕见的例外.


mar*_*inj 7

您可以使用良好的编程实践来防止堆栈溢出,例如:

  1. 非常小心递归,我最近看到由于编写错误的递归CreateDirectory函数导致的SO,如果您不确定您的代码是否100%正确,那么添加将在N次递归调用后停止执行的保护变量.或者更好的是不要写递归函数.
  2. 不要在堆栈上创建大型数组,这可能是隐藏数组,就像一个非常大的数组作为类字段.使用矢量总是更好.
  3. 要非常小心alloca,特别是如果它被放入一些宏定义中.我已经看到由字符串转换宏产生的大量SO,这些宏用于使用alloca进行快速内存分配的for循环.
  4. 确保您的堆栈大小是最佳的,这在嵌入式平台中更为重要.如果你的线程没有做太多,那么给它小堆栈,否则使用更大.我知道预约应该只占用一些地址范围 - 而不是物理内存.

这些是我过去几年看到的最多的SO原因.

对于自动SO查找,您应该能够找到一些静态代码分析工具.