是否有可能从堆栈溢出异常中恢复并在处理异常后继续执行下一条指令?



例如,由于无限递归,这段代码将抛出堆栈溢出,这将导致程序崩溃。是否有一种方法可以处理此异常并避免崩溃并继续执行下一条指令?

#include <iostream>
#include <exception>
template <typename T>
T sum(T firstValue, T secondValue)
{
try{
return firstValue + secondValue;
}
catch(const std::exception &e)
{
std::cerr << "Caught exception: " << e.what() << 'n';
}
}
void causeStackOverflow() {
causeStackOverflow();
}
int main() {
std::cout << "Sum of 3 & 4 is: " << sum(3, 4) << 'n';
try {
causeStackOverflow();
}
catch (const std::exception& e) {
std::cerr << "Caught exception: " << e.what() << 'n'; // If anything can be done here so program can recover and next line can execute?
}
std::cout << "Sum of 1 & 2 is: " << sum(1, 2) << 'n';
return 0;
}

一定有某种方法可以在这里做到这一点。另一个问题是,即使有可能,是否应该这样做?

是否有任何方法可以预测堆栈溢出将会发生的概率?所以我们可以采取一些措施来避免这种情况?

在Windows上,使用Microsoft Visual c++,您可以使用结构化异常处理(SEH)处理堆栈溢出,如下所示:

void causeStackOverflow() {
causeStackOverflow();
}
// Filter for the stack overflow exception.
// This function traps the stack overflow exception, but passes
// all other exceptions through.
int stack_overflow_exception_filter(int exception_code)
{
if (exception_code == EXCEPTION_STACK_OVERFLOW)
{
// Do not call _resetstkoflw here, because
// at this point, the stack isn't yet unwound.
// Instead, signal that the handler (the __except block)
// is to be executed.
return EXCEPTION_EXECUTE_HANDLER;
}
else
return EXCEPTION_CONTINUE_SEARCH;
}
int main() {
// Demonstrate handling a stack overflow 3 times.
for (int i = 0; i < 3; ++i) {
__try {
causeStackOverflow();
}
__except (stack_overflow_exception_filter(GetExceptionCode())) {
std::cout << "Handled!n";
if (!_resetstkoflw()) {
// Failed to reset the stack.  Emergency exit.
exit(-1);
}
}
}
}

重要:堆栈溢出异常会损坏保护页,该保护页将捕获任何后续的堆栈溢出异常。如果您希望能够从同一线程上的另一个堆栈溢出异常中恢复,则必须通过调用_resetstkoflw将这些保护页放回。我强烈建议阅读文档中的整个注释部分。

_resetstkoflw函数从堆栈溢出条件中恢复,允许程序继续而不是因致命的异常错误而失败。如果没有调用_resetstkoflw函数,则在前面的异常之后没有保护页。下次发生堆栈溢出时,不会出现任何异常,进程也会在没有任何警告的情况下终止。

您可以参考MSDN文档来调试堆栈溢出。

使用!analyze命令检查我们是否确实有问题

dt _TEB可用于显示信息。

很难捕捉异常,因为操作系统会杀死进程。c++:从栈溢出获取异常?

最新更新