如何在 C++ 中处理或避免堆栈溢出
在 C++ 中,堆栈溢出通常会导致程序不可恢复的崩溃.对于需要真正健壮的程序,这是一种不可接受的行为,特别是因为堆栈大小是有限的.关于如何处理问题的几个问题.
In C++ a stack overflow usually leads to an unrecoverable crash of the program. For programs that need to be really robust, this is an unacceptable behaviour, particularly because stack size is limited. A few questions about how to handle the problem.
有没有办法通过通用技术来防止堆栈溢出.(一种可扩展、强大的解决方案,包括处理消耗大量堆栈的外部库等)
Is there a way to prevent stack overflow by a general technique. (A scalable, robust solution, that includes dealing with external libraries eating a lot of stack, etc.)
如果发生堆栈溢出,有没有办法处理它们?最好,堆栈会展开,直到有处理程序来处理这种问题.
Is there a way to handle stack overflows in case they occur? Preferably, the stack gets unwound until there's a handler to deal with that kinda issue.
有些语言的线程具有可扩展的堆栈.类似的东西在 C++ 中可能吗?
There are languages out there, that have threads with expandable stacks. Is something like that possible in C++?
如果对 C++ 行为的解决方案有任何其他有用的意见,我们将不胜感激.
Any other helpful comments on the solution of the C++ behaviour would be appreciated.
推荐答案
处理堆栈溢出不是正确的解决方案,相反,您必须确保您的程序不会溢出堆栈.
Handling a stack overflow is not the right solution, instead, you must ensure that your program does not overflow the stack.
不要在堆栈上分配大变量(其中大"取决于程序).确保任何递归算法在已知最大深度后终止.如果递归算法可能会递归未知次数或大量次数,要么自己管理递归(通过维护自己的动态分配的堆栈),要么将递归算法转换为等效的迭代算法
Do not allocate large variables on the stack (where what is "large" depends on the program). Ensure that any recursive algorithm terminates after a known maximum depth. If a recursive algorithm may recurse an unknown number of times or a large number of times, either manage the recursion yourself (by maintaining your own dynamically allocated stack) or transform the recursive algorithm into an equivalent iterative algorithm
必须真正健壮"的程序不会使用吃掉大量堆栈"的第三方或外部库.
A program that must be "really robust" will not use third-party or external libraries that "eat a lot of stack."
请注意,某些平台会在发生堆栈溢出时通知程序并允许程序处理错误.例如,在 Windows 上,会引发异常.此异常不是 C++ 异常,但它是异步异常.而 C++ 异常只能由 throw
语句引发,而异步异常可能在程序执行期间的任何时间引发.不过这是意料之中的,因为堆栈溢出随时可能发生:任何函数调用或堆栈分配都可能溢出堆栈.
Note that some platforms do notify a program when a stack overflow occurs and allow the program to handle the error. On Windows, for example, an exception is thrown. This exception is not a C++ exception, though, it is an asynchronous exception. Whereas a C++ exception can only be thrown by a throw
statement, an asynchronous exception may be thrown at any time during the execution of a program. This is expected, though, because a stack overflow can occur at any time: any function call or stack allocation may overflow the stack.
问题是堆栈溢出可能导致异步异常被抛出,即使是从不期望抛出任何异常的代码(例如,从标记为 noexcept
或 throw()
在 C++ 中).因此,即使您确实以某种方式处理了此异常,您也无法知道您的程序处于安全状态.因此,处理异步异常的最好方法是根本不处理它(*).如果抛出一个,则意味着程序包含错误.
The problem is that a stack overflow may cause an asynchronous exception to be thrown even from code that is not expected to throw any exceptions (e.g., from functions marked noexcept
or throw()
in C++). So, even if you do handle this exception somehow, you have no way of knowing that your program is in a safe state. Therefore, the best way to handle an asynchronous exception is not to handle it at all(*). If one is thrown, it means the program contains a bug.
其他平台可能有类似的方法来处理"堆栈溢出错误,但任何此类方法都可能遇到相同的问题:预期不会导致错误的代码可能会导致错误.
Other platforms may have similar methods for "handling" a stack overflow error, but any such methods are likely to suffer from the same problem: code that is expected not to cause an error may cause an error.
(*) 有一些非常罕见的例外情况.
相关文章