编程语言
首页 > 编程语言> > C++ 栈展开

C++ 栈展开

作者:互联网

C++ 栈展开

Stack Unwinding

当程序抛出一个异常时,程序暂停当前函数的执行过程并立即开始查找(look up)最邻近的与异常匹配的 catch 子句。

为了能够快速处理异常,编译器应该会做一定的记录工作:在每一个 try 语句块的进入点记录对应的 catch 子句能够处理的异常类型。如果发生异常,程序在运行期便可以根据记录的数据来快速查找(look up)是否存在与异常匹配的 catch 子句,从而快速处理异常。不同的编译器的具体策略会有所不同。

std::terminate : 终止当前的程序。默认情况下, std::terminate 会调用 std::abort 。当我们使用 std::set_terminatestd::terminate 安装新的 std::terminate_handler 时,新安装的 std::terminate_handler 最终应该终止程序,如果没有, std::abort 将会被自动调用以终止程序(经过使用 MSVC 和 g++ 测试,确实是这样。See: Unhandled C++ exceptions | Microsoft Docs )。

std::abort : 导致程序异常终止。它不进行清理工作:不会调用自动对象,静态对象和线程局部对象的析构函数。

std::exit : 导致程序正常终止。它会进行一些清理工作:会调用静态对象和线程局部对象的析构函数;但不进行栈展开(stack unwinding):不会调用自动对象的析构函数。

std::abortstd::exit 这两个函数都不会销毁自动对象,因为 stack unwinding 不会被执行起来。如果希望确保所有局部对象的析构函数被调用,应该运用异常机制(捕获异常)或正常返回,然后从 main() 退出程序。

Exceptions and stack unwinding in C++ | Microsoft Docs栈展开(stack unwinding)的描述如下:

In the C++ exception mechanism, control moves from the throw statement to the first catch statement that can handle the thrown type. When the catch statement is reached, all of the automatic variables that are in scope between the throw and catch statements are destroyed in a process that is known as stack unwinding. In stack unwinding, execution proceeds as follows:

  1. Control reaches the try statement by normal sequential execution. The guarded section in the try block is executed.
  2. If no exception is thrown during execution of the guarded section, the catch clauses that follow the try block are not executed. Execution continues at the statement after the last catch clause that follows the associated try block.
  3. If an exception is thrown during execution of the guarded section or in any routine that the guarded section calls either directly or indirectly, an exception object is created from the object that is created by the throw operand. (This implies that a copy constructor may be involved.) At this point, the compiler looks for a catch clause in a higher execution context that can handle an exception of the type that is thrown, or for a catch handler that can handle any type of exception. The catch handlers are examined in order of their appearance after the try block. If no appropriate handler is found, the next dynamically enclosing try block is examined. This process continues until the outermost enclosing try block is examined.
  4. If a matching handler is still not found, or if an exception occurs during the unwinding process but before the handler gets control, the predefined run-time function terminate is called. If an exception occurs after the exception is thrown but before the unwind begins, terminate is called. In these cases, it is implementation-defined whether any stack unwinding occurs at all: throwing an uncaught exception is permitted to terminate the program without invoking any destructors.
  5. If a matching catch handler is found, and it catches by value, its formal parameter is initialized by copying the exception object. If it catches by reference, the parameter is initialized to refer to the exception object. After the formal parameter is initialized, the process of unwinding the stack begins. This involves the destruction of all automatic objects that were fully constructed—but not yet destructed—between the beginning of the try block that is associated with the catch handler and the throw site of the exception. Destruction occurs in reverse order of construction. The catch handler is executed and the program resumes execution after the last handler—that is, at the first statement or construct that is not a catch handler. Control can only enter a catch handler through a thrown exception, never through a goto statement or a case label in a switch statement.

References

标签:std,exception,terminate,C++,handler,析构,catch,展开
来源: https://www.cnblogs.com/ltimaginea/p/15678927.html