try-except
语句
try-except
语句是 Microsoft 特定的扩展,支持 C 和 C++ 语言中的结构化异常处理。
// . . .
__try {
// guarded code
}
__except ( /* filter expression */ ) {
// termination code
}
// . . .
语法
try-except-statement
:
__try
compound-statement
__except (
expression
)
compound-statement
备注
try-except
语句是 Microsoft 对 C 和 C++ 语言的扩展。 它使目标应用程序能够在正常终止程序执行的事件发生时获得控制权。 此类事件称为“结构化异常”,简称“异常”。 处理这些异常的机制称为“结构化异常处理”(SEH)。
有关相关信息,请参阅 try-finally 语句。
异常可能是基于硬件的,也可能是基于软件的。 即使应用程序无法完全从硬件异常或软件异常中恢复,结构化异常处理也很有用。 SEH 可以显示错误信息和捕获应用程序的内部状态来帮助诊断问题。 这对于不易重现的间歇性问题尤其有用。
注意
结构化异常处理适用于 Win32 中的 C 和 C++ 源文件。 但是,这不是专为 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
语句的过程中进程被终止,则不会调用异常处理程序。
为了与以前的版本兼容,除非指定了编译器选项 /Za(禁用语言扩展),否则 _try、_except 和 _leave 与 __try
、__except
、__leave
是同义词。
__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
和 PCONTEXT
在包含文件 <winnt.h> 中定义,而 _EXCEPTION_RECORD
和 _CONTEXT
在包含文件 <excpt.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
另请参阅
反馈
https://aka.ms/ContentUserFeedback.
Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see:提交和查看相关反馈