什么是栈展开?搜索了一遍,但没有找到有启发性的答案!
当前回答
堆栈展开是在运行时从函数调用堆栈中删除函数项的过程。它通常与异常处理有关。在c++中,当发生异常时,函数调用堆栈会线性地搜索异常处理程序,在带有异常处理程序的函数之前的所有条目都将从函数调用堆栈中删除。
其他回答
在Java堆栈中,不宽或不伤人不是很重要(使用垃圾收集器)。在许多异常处理论文中,我看到了这个概念(堆栈展开),特别是那些作者在C或c++中处理异常处理。对于try catch块,我们不应该忘记:在局部块之后释放所有对象的堆栈。
堆栈展开是在运行时从函数调用堆栈中删除函数项的过程。它通常与异常处理有关。在c++中,当发生异常时,函数调用堆栈会线性地搜索异常处理程序,在带有异常处理程序的函数之前的所有条目都将从函数调用堆栈中删除。
在我看来,本文中给出的下图漂亮地解释了堆栈unwind对下一条指令路径的影响(一旦抛出未捕获的异常,将执行):
在图片中:
上面一个是正常的调用执行(没有抛出异常)。 当抛出异常时,位于底部。
在第二种情况下,当发生异常时,将在函数调用堆栈中线性搜索异常处理程序。搜索结束于带有异常处理程序的函数,即带有try-catch块的main(),但不是在从函数调用堆栈中删除它之前的所有条目之前。
我读了一篇博客文章,帮助我理解。
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.
你可以在这里找到完整的帖子。
堆栈展开通常与异常处理有关。这里有一个例子:
void func( int x )
{
char* pleak = new char[1024]; // might be lost => memory leak
std::string s( "hello world" ); // will be properly destructed
if ( x ) throw std::runtime_error( "boom" );
delete [] pleak; // will only get here if x == 0. if x!=0, throw exception
}
int main()
{
try
{
func( 10 );
}
catch ( const std::exception& e )
{
return 1;
}
return 0;
}
在这里,如果抛出异常,分配给pleak的内存将丢失,而分配给s的内存将在任何情况下通过std::string析构函数正确释放。当退出作用域时,在堆栈上分配的对象将被“解开”(这里的作用域是函数func的作用域)。这是通过编译器插入对自动(堆栈)变量析构函数的调用来完成的。
现在,这是一个非常强大的概念,导致称为RAII的技术,即资源获取即初始化,它帮助我们在c++中管理内存、数据库连接、打开的文件描述符等资源。
现在这允许我们提供异常安全保证。