EXCEPTION_EXECUTE_HANDLER (1) 异常已经被识别,也即当前的这个异常错误,系统已经找到了并能够确认,这个__except模块就是正确的异常处理模块。控制流将进入到__except模块中,当except代码块运行结束后,系统会认为异常已经处理,于是允许应用程序继续执行。
全局展开 异常产生,系统夺回控制权,搜索与try块匹配的except块。因为F1中的try块匹配的是finally,于是系统调用栈中向上搜索到另一个try块,当异常过滤程序计算结果为EXCEPTION_EXECUTE_HANDLER,系统必须进行全局展开。马上在发生异常出的finally块中开始全局展开。寻找所有未完成的finally块的try块
如果一个异常发生在try、finally块中,且在其上层没有try、except,进程立刻终止。即全局展开不会发送,finally块也不会执行。
在finally中放入return可以阻止全局展开进行
//以空格作为分割符的符号个数 //内存复制功能 // test1.cpp : 定义控制台应用程序的入口点。 // #include <Windows.h> #include <tchar.h> #include <winternl.h> #include <Shlwapi.h> #include<iostream> int Sub1(const char* v1); CHAR* Sub2(CHAR*Source, size_t Destination); const char* x = "11 11 1 ssssssssssss"; int main() { printf("%d ",Sub1(x)); printf("%d ",Sub1(NULL)); printf("%s ", Sub2("11 11 1 ssssssssssss",50)); return 0; } int Sub1(const char* v1) { int length = -1; char* Buffer = NULL; __try { Buffer = (char*)malloc(strlen(v1) + 1); strcpy(Buffer, v1); char* pszToken = strtok(Buffer,"s");//在第一次调用 strtok 时,函数跳过前导分隔符(连在一起算一个)并返回指向在 strToken的第一个标记的指针,以空字符终止标记。 通过一系列 strtok 的调用,多个标记将被从 strToken 的其余部分拆开。 每个 strtok调用通过插入 null 字符在该调用返回 token 之后修改strToken。 for (; pszToken != NULL; pszToken = strtok(NULL, "s")) length++; length++; } __except(EXCEPTION_EXECUTE_HANDLER) { } free(Buffer); return(length); } CHAR* Sub2(CHAR*Source, size_t size) { CHAR* v1 = NULL; __try { v1 = (CHAR*)malloc(size); memcpy(v1, Source, size); } __except(EXCEPTION_EXECUTE_HANDLER) { free(v1); v1 = NULL; } return(v1); }
EXCEPTION_CONTINUE_EXECUTION (–1) 异常被忽略或已被修复,程序控制留跳转到导致异常的那条指令,并尝试重新执行这条指令,继续恢复运行。需要很谨慎
// // // test1.cpp : 定义控制台应用程序的入口点。 // #include <Windows.h> #include <tchar.h> #include <winternl.h> #include <Shlwapi.h> #include<iostream> TCHAR BufferData[100]; int Sub1(const char* v1); CHAR* Sub2(CHAR*Source, size_t Destination); LONG Filter1(TCHAR **v1); void Sub5(); const char* x = "11 11 1 ssssssssssss"; int main() { Sub5(); // printf("%d ",Sub1(NULL)); //printf("%d ",Sub1(NULL)); //printf("%s ", Sub2("11 11 1 ssssssssssss",50)); return 0; } int Sub1(const char* v1) { int length = -1; char* Buffer = NULL; __try { Buffer = (char*)malloc(strlen(v1) + 1); strcpy(Buffer, v1); char* pszToken = strtok(Buffer,"s");//在第一次调用 strtok 时,函数跳过前导分隔符(连在一起算一个)并返回指向在 strToken的第一个标记的指针,以空字符终止标记。 通过一系列 strtok 的调用,多个标记将被从 strToken 的其余部分拆开。 每个 strtok调用通过插入 null 字符在该调用返回 token 之后修改strToken。 for (; pszToken != NULL; pszToken = strtok(NULL, "s")) length++; length++; } __except(EXCEPTION_EXECUTE_HANDLER) { } free(Buffer); return(length); } CHAR* Sub2(CHAR*Source, size_t size) { CHAR* v1 = NULL; __try { v1 = (CHAR*)malloc(size); memcpy(v1, Source, size); } __except(EXCEPTION_EXECUTE_HANDLER) { free(v1); v1 = NULL; } return(v1); } void Sub5() { int v1 = 0; TCHAR *pBuffer = NULL; __try { *pBuffer = TEXT('j');//第一次 指针没有初始化 进Filter1()返回EXCEPTION_CONTINUE_EXECUTION 需要很谨慎 v1 = 5 / v1;//第二次发生异常 v1初始化为0 } __except(Filter1(&pBuffer)) { MessageBox(NULL, NULL, NULL, MB_OK); } MessageBox(NULL,TEXT("ssss"), NULL, MB_OK); } LONG Filter1(TCHAR **v1) { if (*v1 == NULL) { *v1 = BufferData; printf("hello"); return(EXCEPTION_CONTINUE_EXECUTION); } return(EXCEPTION_EXECUTE_HANDLER); }
EXCEPTION_CONTINUE_SEARCH (0) 异常不被识别,也即当前的这个__except模块不是这个异常错误所对应的正确的异常处理模块。系统将继续到上一层的try-except域中继续查找一个恰当的__except模块。
单纯返回常量EXCEPTION_CONTINUE_SEARCH,系统寻找到在它上一层的一个try块并调用对应的异常过滤程序中的函数。(此时若出现异常终止程序会先忽略)
//以空格作为分割符的符号个数 //内存复制功能 // test1.cpp : 定义控制台应用程序的入口点。 // #include <Windows.h> #include <tchar.h> #include <winternl.h> #include <Shlwapi.h> #include<iostream> TCHAR BufferData[100]; void Sub6(); void Sub6_BELONG(TCHAR *v1); LONG Filter2(TCHAR **v1); int main() { Sub6(); //Sub5(); // printf("%d ",Sub1(NULL)); //printf("%d ",Sub1(NULL)); //printf("%s ", Sub2("11 11 1 ssssssssssss",50)); return 0; } void Sub6() { TCHAR *pBuffer = NULL; __try { Sub6_BELONG(pBuffer); } __except(Filter2(&pBuffer)) { MessageBox(NULL, NULL, NULL, MB_OK); } } void Sub6_BELONG(TCHAR *v1) { __try { *v1 = TEXT('