在异常发生后,应该立刻获取异常代码,以确切知道发生了什么异常,__except 块或者过滤表达式可以通过使用 GetExceptionCode() 函数来做到这一点。
需要注意的是,编译器会强制过滤函数本身不能调用 GetExceptionCode(),比如:
filter(...) {
GetExceptionCode(); //错误
}
__try {
....
}
__except (filter(...)) {
...
}
通常的做法是在过滤表达式中调用它,比如下面:- __except (filter(GetExceptionCode())) { }
复制代码 这样,所获得的异常代码作为参数传递给一个由用户提供的过滤函数(filter).
在这种情况中,过滤函数决定返回过滤表达式的值,这个值必须是三个固定的枚举值之一(参考:《[异常处理] try 与 except 》)
GetExceptionCode() 函数可以返回许多不同的异常代码值,比如在尝试读、写或执行进程没有访问权限的虚拟地址时返回 EXCEPTION_ACCESS_VIOLATION ;又比如被 0 除时,返回 EXCEPTION_INT_DIVIDE_BY_ZERO 。
测试代码:
[C] 纯文本查看 复制代码 // excep-1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.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 _tmain(int argc, _TCHAR* argv[])
{
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");
}
|