try-finally 语句

try-finally 语句是 Microsoft 特定的扩展,支持 C 和 C++ 语言中的结构化异常处理

语法

以下语法描述 try-finally 语句:

    // . . .
    __try {
        // guarded code
    }
    __finally {
        // termination code
    }
    // . . .

语法

try-finally-statement
__try compound-statement __finally compound-statement

try-finally 语句是 Microsoft C 和 C++ 语言扩展,它们使目标应用程序能够确保在代码块的执行被中断时执行清理。 清理包括多个任务,如释放内存、关闭文件和释放文件句柄。 try-finally 语句对此类例程特别有用:具有几个位置,在这些位置上执行了检查以找出可能导致例程提前返回内容的错误。

有关相关的信息和代码示例,请参阅 try-except 语句。 有关常规的结构化异常处理的详细信息,请参阅结构化异常处理。 有关使用 C++/CLI 处理托管应用程序中的异常的详细信息,请参阅下面的/clr异常处理

注意

结构化异常处理适用于 Win32 中的 C 和 C++ 源文件。 但是,这不是专门为 C++ 设计的。 您可通过使用 C++ 异常处理来确保提高代码的可移植性。 此外,C++ 异常处理更为灵活,因此它可以处理任何类型的异常。 对于 C++ 程序,建议使用 C++ 异常处理机制(trycatch、和 throw 语句)。

__try 子句后的复合语句是受保护节。 __finally 子句后的复合语句是终止处理程序。 该处理程序将指定在退出受保护分区时执行的一组操作,无论该受保护分区是因异常(非正常终止)还是标准贯穿(正常终止)而退出。

控制权通过简单的顺序执行(贯穿)传递到 __try 语句。 当控件进入 __try 时,其关联的处理程序将变为活动状态。 如果控制流到达 try 块的末尾,执行将继续,如下所示:

  1. 调用终止处理程序。

  2. 当终止处理程序完成时,执行在 __finally 语句后继续。 无论受保护部分如何结束(例如,通过受保护主体外部的 goto 或通过 return 语句),在控制流移出受保护部分之前,都会执行终止处理程序。

    __finally 语句不会阻碍搜索相应的异常处理程序。

如果 __try 块中发生异常,则操作系统必须找到该异常的处理程序,否则程序将失败。 如果找到处理程序,则会执行所有 __finally 块,并且执行将在处理程序中恢复。

例如,假设一个函数调用系列将函数 A 链接到函数 D,如下图所示。 每个函数均有一个终止处理程序。 如果异常在函数 D 中引发并在函数 A 中得到处理,则当系统展开堆栈时,按以下顺序调用终止处理程序:D、C、B。

Diagram of the order of termination handler execution.

该图从函数 A 开始,函数 A 调用函数 B,函数 B 调用函数 C,函数 C 调用函数 D。函数 D 引发异常。 然后按以下顺序调用终止处理程序:D 的终止处理程序,然后是 C 的,然后是 B 的,然后 A 处理异常。

终止处理程序执行顺序

注意

try-finally 的行为与支持使用 finally 的其他语言(如 C#)的行为不同。 单个 __try 可以拥有 __finally__except,不能同时拥有二者。 如果同时使用二者,则外部 try-except 语句必须包含内部 try-finally 语句。 指定何时执行每个块的规则也有所不同。

为了与以前的版本兼容,除非指定了编译器选项 /Za(禁用语言扩展),否则 _try_finally_leave__try__finally__leave 的同义词。

__leave 关键字

__leave 关键字仅在 try-finally 语句的受保护节有效,其作用是跳到受保护节的末尾。 执行将在终止处理程序中的第一个语句处继续。

goto 语句还可以跳出受保护部分,但由于它调用了堆栈展开,因此会降低性能。 __leave 语句将更为有效,因为它不会导致堆栈展开。

异常终止

使用 longjmp 运行时函数退出 try-finally 语句被视为异常终止。 跳转到 __try 语句是非法的,但跳出该语句是合法的。 必须运行在起点(__try 块的正常中止)和终点(处理异常的 __except 块)之间处于活动状态的所有 __finally 语句。 这称为“局部展开”。

如果 __try 块因某个原因提前终止(包括跳出该块),则系统将执行关联的 __finally 块作为展开堆栈这一过程的一部分。 在这种情况下,如果从 __finally 块内调用,AbnormalTermination 函数将返回 true;否则,它将返回 false

如果在执行 try-finally 语句期间结束进程,则不会调用终止处理程序。

结束 Microsoft 专用

另请参阅

编写终止处理程序
Structured Exception Handling (C/C++)
关键字
终止处理程序语法