2024-11-15 10:00:05

什么是栈展开?

什么是栈展开?搜索了一遍,但没有找到有启发性的答案!


当前回答

在我看来,本文中给出的下图漂亮地解释了堆栈unwind对下一条指令路径的影响(一旦抛出未捕获的异常,将执行):

在图片中:

上面一个是正常的调用执行(没有抛出异常)。 当抛出异常时,位于底部。

在第二种情况下,当发生异常时,将在函数调用堆栈中线性搜索异常处理程序。搜索结束于带有异常处理程序的函数,即带有try-catch块的main(),但不是在从函数调用堆栈中删除它之前的所有条目之前。

其他回答

堆栈展开主要是c++的概念,处理当堆栈分配的对象的作用域退出时(正常退出或通过异常退出)如何销毁。

假设你有这样一段代码:

void hw() {
    string hello("Hello, ");
    string world("world!\n");
    cout << hello << world;
} // at this point, "world" is destroyed, followed by "hello"

在Java堆栈中,不宽或不伤人不是很重要(使用垃圾收集器)。在许多异常处理论文中,我看到了这个概念(堆栈展开),特别是那些作者在C或c++中处理异常处理。对于try catch块,我们不应该忘记:在局部块之后释放所有对象的堆栈。

所有这些都与c++有关:

定义: 当您静态地创建对象(在堆栈上而不是在堆内存中分配对象)并执行函数调用时,它们是“堆叠起来的”。

当一个作用域(由{和}分隔的任何内容)退出(通过使用return XXX;,到达作用域的末尾或抛出异常)时,该作用域内的所有内容都被销毁(对所有内容调用析构函数)。这个销毁局部对象并调用析构函数的过程称为堆栈展开。

您有以下与堆栈展开相关的问题:

avoiding memory leaks (anything dynamically allocated that is not managed by a local object and cleaned up in the destructor will be leaked) - see RAII referred to by Nikolai, and the documentation for boost::scoped_ptr or this example of using boost::mutex::scoped_lock. program consistency: the C++ specifications state that you should never throw an exception before any existing exception has been handled. This means that the stack unwinding process should never throw an exception (either use only code guaranteed not to throw in destructors, or surround everything in destructors with try { and } catch(...) {}).

如果任何析构函数在堆栈展开过程中抛出异常,那么就会出现未定义的行为,这可能导致程序意外终止(最常见的行为)或整个宇宙结束(理论上是可能的,但在实践中尚未观察到)。

每个人都谈论过c++中的异常处理。但是,我认为堆栈展开还有另一个内涵,它与调试有关。调试器必须在应该转到当前帧之前的帧时进行堆栈展开。然而,这是一种虚拟unwind,因为当它回到当前帧时需要倒带。例如gdb中的up/down/bt命令。

在我看来,本文中给出的下图漂亮地解释了堆栈unwind对下一条指令路径的影响(一旦抛出未捕获的异常,将执行):

在图片中:

上面一个是正常的调用执行(没有抛出异常)。 当抛出异常时,位于底部。

在第二种情况下,当发生异常时,将在函数调用堆栈中线性搜索异常处理程序。搜索结束于带有异常处理程序的函数,即带有try-catch块的main(),但不是在从函数调用堆栈中删除它之前的所有条目之前。