基于帧的异常处理
基于帧的异常处理程序允许处理在特定代码序列中可能发生的异常。 基于帧的异常处理程序由以下元素组成。
- 受保护的代码正文
- 筛选器表达式
- 异常处理程序块
系统以特定于语言的语法声明基于帧的异常处理程序。 例如,在 Microsoft C/C++ 优化编译器中,系统使用 __try 和 __except 块来实现它们。 有关详细信息,请参阅处理程序语法。
代码的受保护正文是一组或多个语句,筛选器表达式和异常处理程序块会为这些语句提供异常处理保护。 受保护的正文可以是代码块、一组嵌套块或整个过程或函数。 受保护的正文通过 Microsoft C/C++ 优化编译器括在大括号 ({}) 中,后跟 __try 关键字。
基于帧的异常处理程序的筛选器表达式是在受保护的正文中发生异常时由系统计算的表达式。 此评估会导致系统执行以下其中一项操作。
- 系统停止搜索异常处理程序、还原计算机状态,并在发生异常的位置继续执行线程。
- 系统继续搜索异常处理程序。
- 系统将控制权转移给异常处理程序,线程在找到异常处理程序所在的堆栈帧中继续按顺序执行。 如果处理程序不在发生异常的堆栈帧中,则系统将展开堆栈,保留当前堆栈帧和任何其他堆栈帧,直到返回到异常处理程序的堆栈帧。 在执行异常处理程序之前,将对由于控制权转移到异常处理程序而终止的代码的任何受保护正文执行终止处理程序。 有关终止处理程序的详细信息,请参阅终止处理。
筛选器表达式可以是简单的表达式,也可以调用筛选器函数来尝试处理异常。 你可以从筛选器表达式中调用 GetExceptionCode 和 GetExceptionInformation 函数,以获取有关正在筛选的异常的信息。 GetExceptionCode 返回标识异常类型的代码,GetExceptionInformation 返回一个指向 EXCEPTION_POINTERS 结构的指针,该结构包含指向 CONTEXT 和 EXCEPTION_RECORD 结构的指针。
这些函数无法从筛选器函数内部调用,但它们的返回值可以作为参数传递给筛选器函数。 GetExceptionCode 可以在异常处理程序块中使用,但 GetExceptionInformation 不能,因为它指向的信息通常在堆栈上,并且当控制权转移到异常处理程序时此信息会被销毁。 但是,应用程序可以将信息复制到安全存储,以使其可供异常处理程序使用。
筛选器函数的优点是它可以处理异常并返回一个值,使系统从异常发生点继续执行。 相反,对于异常处理程序块,会从异常处理程序而不是从异常点开始按顺序继续执行。
处理异常可能就像记录错误并设置稍后将检查的标志、打印警告或错误消息或采取一些其他受限操作一样简单。 如果可以继续执行,则可能还需要通过修改上下文记录来更改计算机状态。 有关处理页面错误异常的筛选器函数的示例,请参阅使用虚拟内存函数。
UnhandledExceptionFilter 函数可用作筛选器表达式中的筛选器函数。 它会返回 EXCEPTION_EXECUTE_HANDLER,除非正在调试进程,在这种情况下,它将返回 EXCEPTION_CONTINUE_SEARCH。