该 try-except 语句是一个 特定于Microsoft的 扩展,支持 C 和 C++ 语言中的结构化异常处理。
// . . .
__try {
// guarded code
}
__except ( /* filter expression */ ) {
// termination code
}
// . . .
语法
try-except-statement:
__trycompound-statement__except (expression)compound-statement
注解
该 try-except 语句是 C 语言和C++语言的Microsoft扩展。 它使目标应用程序能够控制正常终止程序执行的事件的时间。 此类事件称为 结构化异常,或短时间内 的异常 。 处理这些异常的机制称为 结构化异常处理 (SEH)。
有关相关信息,请参阅 try-finally 语句。
异常可以是基于硬件的,也可以是基于软件的。 即使应用程序无法完全从硬件或软件异常中恢复,结构化异常处理也很有用。 SEH 可以显示错误信息并捕获应用程序的内部状态,以帮助诊断问题。 对于不容易重现的间歇性问题,它特别有用。
注释
结构化异常处理适用于 C 和C++源文件的 Win32。 但是,它不是专门为C++设计的。 可以使用C++异常处理来确保代码更易于移植。 此外,C++异常处理更灵活,因为它可以处理任何类型的异常。 对于C++程序,建议使用本机C++异常处理: try、catch 和 throw 语句。
子句后面的 __try 复合语句是 正文 或 受保护的 节。 该 __except 表达式也称为 筛选器 表达式。 其值确定异常的处理方式。 子句后面的 __except 复合语句是异常处理程序。 处理程序指定在执行正文节期间引发异常时要执行的作。 执行继续,如下所示:
执行受保护的节。
如果在执行受保护的节期间未发生异常,则子句后
__except语句将继续执行。如果在执行受保护的节期间或受保护的节调用的任何例程中发生异常,则会
__except计算表达式。 有三种可能的值:EXCEPTION_CONTINUE_EXECUTION(-1)异常将被消除。 在发生异常时继续执行。EXCEPTION_CONTINUE_SEARCH(0) 无法识别异常。 继续搜索处理程序的堆栈,首先搜索包含try-except语句,然后搜索具有下一个最高优先级的处理程序。EXCEPTION_EXECUTE_HANDLER(1) 识别异常。 通过执行__except复合语句将控制权传输到异常处理程序,然后在块之后__except继续执行。
表达式 __except 的计算结果为 C 表达式。 限制为单个值、条件表达式运算符或逗号运算符。 如果需要更广泛的处理,表达式可以调用一个例程,该例程返回上面列出的三个值之一。
每个应用程序可以有自己的异常处理程序。
跳入 __try 语句无效,但跳出一个语句是有效的。 如果在执行 try-except 语句的过程中终止进程,则不会调用异常处理程序。
为了与以前的版本兼容,_try、_except和_leave是同__try__except义词,__leave除非指定编译器选项 /Za (禁用语言扩展)。
__leave 关键字
关键字 __leave 仅在语句的 try-except 受保护的节内有效,其效果是跳转到受保护的节的末尾。 异常处理程序之后的第一个语句将继续执行。
语句 goto 也可以跳出受保护的部分,它不会降低性能,就像 在 try-finally 语句中那样。 这是因为堆栈展开不会发生。 但是,我们建议使用 __leave 关键字而不是 goto 语句。 原因是,如果受保护的节很大或很复杂,则不太可能犯编程错误。
结构化异常处理内部函数
结构化异常处理提供两个可用于 try-except 语句的内部函数: GetExceptionCode 和 GetExceptionInformation。
GetExceptionCode 返回异常的代码(32 位整数)。
内部函数 GetExceptionInformation 返回指向包含有关异常的其他信息的 EXCEPTION_POINTERS 结构的指针。 通过此指针,可以访问硬件异常时存在的计算机状态。 结构如下所示:
typedef struct _EXCEPTION_POINTERS {
PEXCEPTION_RECORD ExceptionRecord;
PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
指针类型PEXCEPTION_RECORD并在 include 文件 <winnt.h> 中定义,并在 _CONTEXT_EXCEPTION_RECORD include 文件<摘录PCONTEXT.h 中定义>
可以在异常处理程序中使用 GetExceptionCode 。 但是,只能在 GetExceptionInformation 异常筛选器表达式中使用。 它指向的信息通常位于堆栈上,当控件传输到异常处理程序时不再可用。
终止处理程序中提供了内部函数 AbnormalTermination 。 如果 try-finally 语句的正文按顺序终止,则返回 0。 在所有其他情况下,它返回 1。
<excpt.h> 为这些内部函数定义一些备用名称:
GetExceptionCode 等效于 _exception_code
GetExceptionInformation 等效于 _exception_info
AbnormalTermination 等效于 _abnormal_termination
示例:
// exceptions_try_except_Statement.cpp
// Example of try-except and try-finally statements
#include <stdio.h>
#include <windows.h> // for EXCEPTION_ACCESS_VIOLATION
#include <excpt.h>
int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
puts("in filter.");
if (code == EXCEPTION_ACCESS_VIOLATION)
{
puts("caught AV as expected.");
return EXCEPTION_EXECUTE_HANDLER;
}
else
{
puts("didn't catch AV, unexpected.");
return EXCEPTION_CONTINUE_SEARCH;
}
}
int main()
{
int* p = 0x00000000; // pointer to NULL
puts("hello");
__try
{
puts("in try");
__try
{
puts("in try");
*p = 13; // causes an access violation exception;
}
__finally
{
puts("in finally. termination: ");
puts(AbnormalTermination() ? "\tabnormal" : "\tnormal");
}
}
__except(filter(GetExceptionCode(), GetExceptionInformation()))
{
puts("in except");
}
puts("world");
}
输出
hello
in try
in try
in filter.
caught AV as expected.
in finally. termination:
abnormal
in except
world