该 try-finally
语句是一个 特定于Microsoft的 扩展,支持 C 和 C++ 语言中的结构化异常处理。
语法
以下语法描述了 try-finally
该语句:
// . . .
__try {
// guarded code
}
__finally {
// termination code
}
// . . .
语法
try-finally-statement
:
__try
compound-statement
__finally
compound-statement
该 try-finally
语句是 C 和 C++ 语言的Microsoft扩展,使目标应用程序能够保证在代码块执行中断时执行清理代码。 清理包括解除分配内存、关闭文件和释放文件句柄等任务。 该 try-finally
语句对于具有多个位置的例程特别有用,这些例程检查了可能导致例程过早返回的错误。
有关相关信息和代码示例,请参阅 try-except
语句。 有关结构化异常处理的详细信息,请参阅 结构化异常处理。 有关使用 C++/CLI 在托管应用程序中处理异常的详细信息,请参阅下面的/clr
异常处理。
注释
结构化异常处理适用于 C 和C++源文件的 Win32。 但是,它不是专门为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 开头,该函数调用函数 B,后者调用函数 C,后者调用函数 D。函数 D 引发异常。 然后按以下顺序调用终止处理程序:D 的终止处理程序、C 的、B 的,然后 A 处理异常。
终止处理程序执行的顺序
注释
try-finally 的行为不同于支持使用 finally
的其他一些语言,例如 C# 。 一个可能 __try
具有两者,但不能同时 __finally
具有和 __except
。 如果两者一起使用在一起,则外部 try-except 语句必须包含内部 try-finally 语句。 指定每个块执行时间的规则也不同。
为了与以前的版本、_try
和_leave
_finally
同义词兼容__try
__finally
,__leave
除非指定编译器选项/Za
(禁用语言扩展)。
__leave 关键字
关键字 __leave
仅在语句的 try-finally
受保护的节内有效,其效果是跳转到受保护的节的末尾。 在终止处理程序的第一个语句处继续执行。
语句 goto
也可以跳出受保护的节,但它会降低性能,因为它调用堆栈展开。 该 __leave
语句更高效,因为它不会导致堆栈展开。
异常终止
try-finally
使用 longjmp 运行时函数退出语句被视为异常终止。 跳入一 __try
份声明是不合法的,但从一份声明中跳出来是合法的。 必须在出发点(块的正常终止__try
)和处理异常的块(__except
处理异常的块)之间处于活动状态的所有__finally
语句。 它称为 本地展开。
__try
如果由于任何原因(包括跳出块)而过早终止块,则系统将执行关联的__finally
块作为展开堆栈过程的一部分。 在这种情况下,如果从块内部__finally
调用,则AbnormalTermination
函数返回true
;否则返回 false
。
如果在执行 try-finally
语句的过程中终止进程,则不会调用终止处理程序。
特定于 END Microsoft