《Windows核心编程》之“SEH”

来源:互联网 发布:淘宝退货卖家没收到货 编辑:程序博客网 时间:2024/06/05 20:08

    SEH,Structured Exception Handling(结构化异常处理),包括两种类型:一是Termination Handling,即终止处理;另一个是Exception Handling。本文主要介绍Termination Handling,而对于Exception Handling,我倾向选择使用C++的exception机制代替。


一、Advantages of Termination Handling

1,清理工作集中在一个地方执行,并且保证能得到执行,从而简化了错误处理。

    (一种好的资源管理方式,比如:文件、内存、句柄等)

2,提高代码可读性。

    (避免了正常流程代码和错误处理代码的交缠)

3,让代码更易维护。

    (错误处理代码集中在一个地方维护或修改)

4,如果正确使用,它们对程序性能和体积的影响是微小的。

    (后面将展示它的使用规则)


二、TH的三个关键字

    VC/C++编译器支持TH相关的关键字:__try    __finally    __leave

1,try块

    包裹待保护的代码块

2,finally函数

    可以将它当作一个函数看。不论try块中的代码是正常执行完成还是异常跳出,finally函数都会被执行。异常跳出包括使用return、break、continue、goto等方式和软件异常,finally函数会插入到这些跳出流程之前执行。

3,leave关键字

    为了避免try块中的return等语句导致的局部展开,推荐使用leave关键字统一替换这类语句。局部展开会影响程序性能。


三、TH代码与非TH代码的对比

1,非TH代码示例

BOOL Funccarama1(){    HANDLE hFile = INVALID_HANDLE_VALUE;PVOID pvBuf = NULL;DWORD dwNumBytesRead;BOOL bOk;hFile = CreateFile(TEXT("SOMEDATA.DAT"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);if (hFile == INVALID_HANDLE_VALUE){    return(FALSE);}    pvBuf = VirtualAllocEx(NULL, 1024, MEM_COMMIT, PAGE_READWRITE);if (pvBuf == NULL){    CloseHandle(hFile);return(FALSE);}bOk = ReadFile(hFile, pvBuf, 1024, &dwNumBytesRead, NULL);if (!bOk || (dwNumBytesRead == 0){    VirtualFree(pvBuf, MEM_RESERVE | MEM_DECOMMIT);    CloseHandle(hFile);return(FALSE);}// Do some calculation on the data....// Clean up all the resources.VirtualFree(pvBuf, MEM_RESERVE | MEM_DECOMMIT);CloseHandle(hFile);return(FALSE);}

    代码中,每一次对资源的操作,都需要处理错误,并在错误处理模块中清理之前打开的所有资源。随着资源的增加,这个错误处理会更复杂。此外,对错误处理的维护也比较麻烦,需要修改多处代码。


2,TH代码示例

    下面将用TH改写上述示例代码

BOOL Funccarama4(){    // IMPORTANT: Initalize all variables to assume failure.    HANDLE hFile = INVALID_HANDLE_VALUE;PVOID pvBuf = NULL;// Assume that function will not execute successfully.BOOL bFunctionOk = FALSE;__try {    DWORD dwNumBytesRead;    BOOL bOk;        hFile = CreateFile(TEXT("SOMEDATA.DAT"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);    if (hFile == INVALID_HANDLE_VALUE)    __leave;            pvBuf = VirtualAllocEx(NULL, 1024, MEM_COMMIT, PAGE_READWRITE);    if (pvBuf == NULL)    __leave;        bOk = ReadFile(hFile, pvBuf, 1024, &dwNumBytesRead, NULL);    if (!bOk || (dwNumBytesRead == 0)    __leave;        // Do some calculation on the data.    ...// Indicate that the entire function executed successfully.bFunctionOk = TRUE;}__finally {    ///    // Clean up all the resources.///if (pvBuf != NULL)        VirtualFree(pvBuf, MEM_RESERVE | MEM_DECOMMIT);if (hFile != INVALID_HANDLE_VALUE)       CloseHandle(hFile);}// Continue processing.return(bFunctionOk);}


四、TH的基本规则

    我们以上面的示例为参考,总结几条规则,如下:

1,把资源相关的变量,初始化为false型的值.

    (termination handler主要用于集中清理资源,在finally函数中,会判断资源是否被释放了)

2,定义一个局部的返回值变量bFunctionOk

    (统一返回值)

3,可以在finally函数中调内部函数“AbnormalTermination()”获知是否执行try块。


五、Termination Handling .Vs Exception Handling

    比较《Windows核心编程》第23章和24章,可以发现:

1,EH事实上是TH的加强版,当EX的except函数的参数是“EXCEPTION_EXECUTE_HANDLER”时(我把except当作函数看),它会强制吞下所有的异常,并执行except函数内的语句和except函数后面的语句。

2,如果纯粹是管理资源,可以选择轻量版的TH。

3,EH还可以增加“异常过滤功能”。

4,EH可以提高软件运行的稳定性,它会吞下尽可能多的异常,不会因为一些偶然的硬件错误,而导致进程崩溃。


五、关于SEH和C++ exception

    在《Windows核心编程》第25章中,提到了SEH和C++ exception机制的选择问题。

1,C++ exception机制仅适用于C++语言(语言局限),它需要C++编译器对C++对象的支持。

2,SEH仅适用于Windows平台(平台局限性),在Windows下,C++ exception也是通过SEH来实现的。

3,如果开发者使用的是C++语言,请选择C++ exception替代SEH。

0 0
原创粉丝点击