2024-11-15 10:00:05

什么是栈展开?

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


当前回答

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

在图片中:

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

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

其他回答

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

在图片中:

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

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

我不知道你是否读过这篇文章,但维基百科关于调用堆栈的文章有一个很好的解释。

解除:

Returning from the called function will pop the top frame off of the stack, perhaps leaving a return value. The more general act of popping one or more frames off the stack to resume execution elsewhere in the program is called stack unwinding and must be performed when non-local control structures are used, such as those used for exception handling. In this case, the stack frame of a function contains one or more entries specifying exception handlers. When an exception is thrown, the stack is unwound until a handler is found that is prepared to handle (catch) the type of the thrown exception. Some languages have other control structures that require general unwinding. Pascal allows a global goto statement to transfer control out of a nested function and into a previously invoked outer function. This operation requires the stack to be unwound, removing as many stack frames as necessary to restore the proper context to transfer control to the target statement within the enclosing outer function. Similarly, C has the setjmp and longjmp functions that act as non-local gotos. Common Lisp allows control of what happens when the stack is unwound by using the unwind-protect special operator. When applying a continuation, the stack is (logically) unwound and then rewound with the stack of the continuation. This is not the only way to implement continuations; for example, using multiple, explicit stacks, application of a continuation can simply activate its stack and wind a value to be passed. The Scheme programming language allows arbitrary thunks to be executed in specified points on "unwinding" or "rewinding" of the control stack when a continuation is invoked.

检查[编辑]

堆栈展开是在运行时从函数调用堆栈中删除函数项的过程。它通常与异常处理有关。在c++中,当发生异常时,函数调用堆栈会线性地搜索异常处理程序,在带有异常处理程序的函数之前的所有条目都将从函数调用堆栈中删除。

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

假设你有这样一段代码:

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

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