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++ 异常处理机制(try
、catch
、和 throw
语句)。
__try
子句后的复合语句是受保护节。 __finally
子句后的复合语句是终止处理程序。 该处理程序将指定在退出受保护分区时执行的一组操作,无论该受保护分区是因异常(非正常终止)还是标准贯穿(正常终止)而退出。
控制权通过简单的顺序执行(贯穿)传递到 __try
语句。 当控件进入 __try
时,其关联的处理程序将变为活动状态。 如果控制流到达 try 块的末尾,执行将继续,如下所示:
调用终止处理程序。
当终止处理程序完成时,执行在
__finally
语句后继续。 无论受保护部分如何结束(例如,通过受保护主体外部的goto
或通过return
语句),在控制流移出受保护部分之前,都会执行终止处理程序。__finally
语句不会阻碍搜索相应的异常处理程序。
如果 __try
块中发生异常,则操作系统必须找到该异常的处理程序,否则程序将失败。 如果找到处理程序,则会执行所有 __finally
块,并且执行将在处理程序中恢复。
例如,假设一个函数调用系列将函数 A 链接到函数 D,如下图所示。 每个函数均有一个终止处理程序。 如果异常在函数 D 中引发并在函数 A 中得到处理,则当系统展开堆栈时,按以下顺序调用终止处理程序:D、C、B。
该图从函数 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 专用