编写异常筛选器
您可以通过跳转到异常处理程序的级别或通过继续执行来处理异常。 可以使用筛选表达式来清理问题,而不是使用异常处理程序代码来处理异常并失败。 然后,通过返回 EXCEPTION_CONTINUE_EXECUTION
(-1) ,可以恢复正常流,而无需清除堆栈。
注意
有些异常无法继续。 对这样的异常来说,如果筛选计算结果为 -1,则系统将产生新的异常。 调用 RaiseException
时,将确定异常是否会继续。
例如,下面的代码使用筛选表达式中的函数调用:此函数处理该问题并返回 –1 以继续正常控制流:
// exceptions_Writing_an_Exception_Filter.cpp
#include <windows.h>
int main() {
int Eval_Exception( int );
__try {}
__except ( Eval_Exception( GetExceptionCode( ))) {
;
}
}
void ResetVars( int ) {}
int Eval_Exception ( int n_except ) {
if ( n_except != STATUS_INTEGER_OVERFLOW &&
n_except != STATUS_FLOAT_OVERFLOW ) // Pass on most exceptions
return EXCEPTION_CONTINUE_SEARCH;
// Execute some code to clean up problem
ResetVars( 0 ); // initializes data to 0
return EXCEPTION_CONTINUE_EXECUTION;
}
每当筛选需要执行任何复杂操作时,最好在筛选表达式中使用函数调用。 计算表达式将导致函数的执行,在此示例中,Eval_Exception
。
请注意使用 GetExceptionCode
确定异常。 必须在 __except
语句的筛选表达式内调用此函数。 Eval_Exception
不能调用 GetExceptionCode
,但是它必须具有传递给它的异常代码。
除非异常是整数或浮点溢出,否则此处理程序会将控制权传递给其他处理程序。 如果异常是整数或浮点溢出,则处理程序将调用一个函数(ResetVars
只是一个示例,不是 API 函数)以重置某些全局变量。 __except
语句块(在此示例中为空)无法执行,因为 Eval_Exception
绝不返回 EXCEPTION_EXECUTE_HANDLER
(1)。
使用函数调用是处理复杂筛选器表达式的一个很好的通用方法。 其他两个有用的 C 语言功能是:
条件运算符
逗号运算符
条件运算符在这里通常很有用。 它可用于检查特定返回代码,然后返回两个不同值中的一个。 例如,仅当异常为 STATUS_INTEGER_OVERFLOW
时,下面代码中的筛选器才能识别异常:
__except( GetExceptionCode() == STATUS_INTEGER_OVERFLOW ? 1 : 0 ) {
条件运算符在此示例中的用途主要是进行澄清,因为下面的代码将生成相同的结果:
__except( GetExceptionCode() == STATUS_INTEGER_OVERFLOW ) {
条件运算符在你希望筛选器的计算结果为 –1、EXCEPTION_CONTINUE_EXECUTION
时更有用。
逗号运算符允许按顺序执行多个表达式。 然后返回最后一个表达式的值。 例如,下面的代码将异常代码存储在一个变量中,然后测试它:
__except( nCode = GetExceptionCode(), nCode == STATUS_INTEGER_OVERFLOW )
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈