什么是栈展开?搜索了一遍,但没有找到有启发性的答案!
当前回答
我读了一篇博客文章,帮助我理解。
What is stack unwinding? In any language that supports recursive functions (ie. pretty much everything except Fortran 77 and Brainf*ck) the language runtime keeps a stack of what functions are currently executing. Stack unwinding is a way of inspecting, and possibly modifying, that stack. Why would you want to do that? The answer may seem obvious, but there are several related, yet subtly different, situations where unwinding is useful or necessary: As a runtime control-flow mechanism (C++ exceptions, C longjmp(), etc). In a debugger, to show the user the stack. In a profiler, to take a sample of the stack. From the program itself (like from a crash handler to show the stack). These have subtly different requirements. Some of these are performance-critical, some are not. Some require the ability to reconstruct registers from outer frame, some do not. But we'll get into all that in a second.
你可以在这里找到完整的帖子。
其他回答
堆栈展开是在运行时从函数调用堆栈中删除函数项的过程。它通常与异常处理有关。在c++中,当发生异常时,函数调用堆栈会线性地搜索异常处理程序,在带有异常处理程序的函数之前的所有条目都将从函数调用堆栈中删除。
c++运行时销毁在throw和catch之间创建的所有自动变量。在下面这个简单的例子中,f1()抛出和main()捕获,在B和A类型的对象之间按此顺序在堆栈上创建。当f1()抛出时,将调用B和A的析构函数。
#include <iostream>
using namespace std;
class A
{
public:
~A() { cout << "A's dtor" << endl; }
};
class B
{
public:
~B() { cout << "B's dtor" << endl; }
};
void f1()
{
B b;
throw (100);
}
void f()
{
A a;
f1();
}
int main()
{
try
{
f();
}
catch (int num)
{
cout << "Caught exception: " << num << endl;
}
return 0;
}
这个程序的输出将是
B's dtor
A's dtor
这是因为f1()抛出时程序的调用堆栈看起来像
f1()
f()
main()
因此,当f1()被弹出时,自动变量b被销毁,然后当f()被弹出时,自动变量a被销毁。
希望对大家有所帮助,编码愉快!
堆栈展开主要是c++的概念,处理当堆栈分配的对象的作用域退出时(正常退出或通过异常退出)如何销毁。
假设你有这样一段代码:
void hw() {
string hello("Hello, ");
string world("world!\n");
cout << hello << world;
} // at this point, "world" is destroyed, followed by "hello"
在一般意义上,堆栈“unwind”几乎等同于函数调用的结束和随后的堆栈弹出。
然而,特别是在c++的情况下,堆栈展开必须与c++如何调用自任何代码块开始分配的对象的析构函数有关。在块中创建的对象将按照其分配的相反顺序被释放。
在我看来,本文中给出的下图漂亮地解释了堆栈unwind对下一条指令路径的影响(一旦抛出未捕获的异常,将执行):
在图片中:
上面一个是正常的调用执行(没有抛出异常)。 当抛出异常时,位于底部。
在第二种情况下,当发生异常时,将在函数调用堆栈中线性搜索异常处理程序。搜索结束于带有异常处理程序的函数,即带有try-catch块的main(),但不是在从函数调用堆栈中删除它之前的所有条目之前。