首页 > 代码库 > SEH(structured exception handling)基础篇---终止处理程序
SEH(structured exception handling)基础篇---终止处理程序
前序:最近看SEH看的头晕脑胀/(ㄒoㄒ)/~~,SEH最开始是Windows提供的异常处理机制,只是一个简单的框架,而我们现在使用的SEH都是编译器已经在系统提供的最基础的框架上做了修改的增强版(原始版比较原始,牵扯到大量Windows基础知识,并且需要反汇编看汇编代码来理解。。。。本人现在功力较浅,需要慢慢消化,先看一下增强版,通过C和C++来接触一下。
SEH包含两部分功能:终止处理(termination handling)和异常处理(exception handling)。在这先讲一下终止处理程序。
终止程序确保不管一个代码块(被保护代码(the guarded body))是如何推出的,另一个代码块(终止处理程序)总能被调用和执行。
__try { //Guarded body //... } __finally { //Termination handler //... }
在Guarded body中除非调用ExitProcess,ExitThread,TerminateProcess,TerminateThread来终止进程或线程从而__finally代码块不会被调用,其他情况,终止处理程序都会被调用。
下面通过几个伪代码来理解一下DWORD WhiteLearner_SEH_1(){ DWORD dwTemp;
//等待一个信号 WaitForSingleObject(__hSem, INFINITE); __dwProtectedData = 5; dwTemp = __dwProtectedData; return dwTemp; //信号释放 ReleaseSemaphore(__hSem, 1, NULL); return dwTemp; } DWORD WhiteLearner_SEH_2() { DWORD dwTemp; __try { //等待一个信号 WaitForSingleObject(__hSem, INFINITE); __dwProtectedData = 5; dwTemp = __dwProtectedData; return dwTemp; } __finally { //信号释放 ReleaseSemaphore(__hSem, 1, NULL); }
dwTemp = 9;
return dwTemp; }
可以看出来,WhiteLearner_SEH_1()中没有用SEH,在ReleaseSemaphore之前便return掉,线程便没有机会释放信号量资源,其他线程当然也不会在得到对这个信号量的控制权。不难想象,在等待同一个信号量的其他线程因此再也没有机会运行,这样的执行顺序带来了很严重的问题。然而在WhiteLearner_SEH_2()中我们运用了__finally,在__try中return之前,__finally会提前运行,__finally代码块中代码运行完成后再次返回到__try代码块中return结束线程。注意,__finally代码块后面的代码没有得到运行便直接return了,返回值为5。
下面更详细具体的解释一下终止处理程序的意义:
DWORD WhiteLearner_SEH_3(){ DWORD dwTemp; //等待信号量 WaitForSingleObject(__hSem, INFINITE); dwTemp = Funcinator(__dwProtectedData); //释放信号量 ReleaseSemaphore(__hSem, 1, NULL); return dwTemp; }
这个函数中释放前进行了一系列操作Funcinator,如果操作中存在缺陷导致程序非法访问内存,则会导致Windows错误报告(Windows Error Reporting,WER)弹出对话框:“Application has stopped working”。如果用户取消对话框,则进程直接终止,也就是说信号量没有来的及释放,跟WhiteLearner_SEH_1函数类似。
还有,__finally代码块是程序顺序运行也会执行的代码,并且只要__try代码块没有正常运行结束,__finally代码块就会插入__try中运行。(忽略栈耗尽异常)__finally代码块运行的第三种情况--全局展开,这个在SEH下一部分异常处理再详细介绍。
DWORD WhiteLearner_SEH_4() { DWORD dwTemp = 0; while (dwTemp < 10) { __try { if (dwTemp == 2) continue; if (dwTemp == 3) break; } __finally { dwTemp++; } dwTemp++; } return dwTemp; }
这个函数的返回值是4。具体过程希望读者自己思考。
最后,终止处理程序也可以进行最后所有的清理工作:
DWORD WhiteLearner_SEH_5() { HANDLE hFile = INVALID_HANDLE_VALUE; PVOID pvBuf = NULL; BOOL bFunctionOk = FALSE; __try { DWORD dwNumBytesRead; BOOL IsOk; hFile = CreateFile(TEXT("SOMEDATA>DAT"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE){ //进入__finally __leave; } pvBuf = VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE); if (pvBuf == NULL) { __leave; } IsOk = ReadFile(hFile, pvBuf, 0x1000, &dwNumBytesRead, NULL); if (!IsOk || dwNumBytesRead == 0) { __leave; } bFunctionOk = TRUE; } __finally { if (pvBuf != NULL) { VirtualFree(pvBuf, MEM_RELEASE | MEM_DECOMMIT); } if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } } return(bFunctionOk); }
通过这次介绍大家应该能感受到终止处理程序的强大功能,总结一下有下面几条:
1.因为清理工作集中在一个地方执行,并且保证能得到执行,从而简化了错误处理。
2.提高了代码的可读性。
3.让代码更容易维护。
4.如果正常使用,他们对程序性能和体积的影响是微小的。
感谢大家阅读,本人现在也在黑暗中摸索前进,欢迎互相讨论,互相学习。
参考资料:《WINDOWS核心编程》
大神博客http://www.cnblogs.com/lanrenxinxin/p/4631836.html#3340777
SEH(structured exception handling)基础篇---终止处理程序