簡記Windows結構化異常處理之“終止處理”

=============================================================

標題:簡記Windows結構化異常處理之“終止處理”

備註:

日期:2011.3.19

姓名:朱銘雷

=============================================================

結構化異常處理(SEH),可以讓代碼的功能部分同異常處理或者資源回收部分分離開來,使功能部分的代碼更清晰可讀,同時讓代碼的健壯性更好。SEH包含兩種結構,一種叫做“終止處理”,一種叫做“異常處理”。

       終止處理

       __try

{}

__finally

{}

通常在這種結構中,__try塊中的代碼爲主要功能代碼,__finally塊中的代碼回收資源或處理異常和錯誤。__finally塊中的代碼肯定會被執行(除非線程或進程被終止),即使__try塊中的代碼包含return,goto等語句,或者存在內存訪問異常。

       “終止處理”結構示例1

BOOL ReadFileData()

{

       HANDLE hFile = INVALID_HANDLE_VALUE;

       PVOID pvBuf = NULL;

       BOOL bRet = FALSE;

 

       __try

       {

              hFile = CreateFile(_T("filedata.dat"), GENERIC_READ,

                     FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

              if (hFile == INVALID_HANDLE_VALUE)

                     __leave;

             

              const int PAGESIZE = 4096;

              pvBuf = VirtualAlloc(NULL, PAGESIZE, MEM_COMMIT, PAGE_READWRITE);

              if (pvBuf == NULL)

                     __leave;

 

              BOOL bOk = FALSE;

              DWORD dwNumberOfBytesRead = 0;

              bOk = ReadFile(hFile, pvBuf, PAGESIZE, &dwNumberOfBytesRead, NULL);

              if (!bOk)

                     __leave;

 

              bRet = TRUE;

       }

       __finally

       {

              if (pvBuf != NULL)

                     VirtualFree(pvBuf, 0, MEM_DECOMMIT | MEM_RELEASE);

              if (hFile != INVALID_HANDLE_VALUE)

                     CloseHandle(hFile);

       }

       return bRet;

}

       這段程序將資源回收,全部放在了__finally塊,使程序更加整潔,可讀性更好。__leave使控制流跳轉到__try塊結尾,然後正常進入__finally塊,這樣程序開銷很小。

       “終止處理”結構示例2

DWORD ProcessData()

{

       DWORD dwTemp = 0;

       __try

       {

              WaitForSingleObject(g_hSem, INFINITE);

              dwTemp = FunA(g_dwProtectedData);

       }

       __finally

       {

              ReleaseSemaphore(g_hSem, 1, NULL);

       }

       return dwTemp;

}

       這段程序如果沒有使用SEH結構,如果FunA函數中存在非法內存訪問,Windows將彈出WER對話框。如果點擊取消,進程終止,將導致信號量得不到釋放,其他等待該信號量的線程很可能永遠得不到時間片。

       通常不要在__try塊中和__finally塊中,使用return,goto,continue,break語句,這些語句會造成“提前退出”和“局部展開”,一是對性能有影響,二是有些語句可能得不到執行。

       “終止處理”結構示例3

DWORD ProcessData()

{

       DWORD dwTemp = 0;

       __try

       {

              WaitForSingleObject(g_hSem, INFINITE);

              dwTemp = FunA(g_dwProtectedData);

       }

       __finally

       {

              ReleaseSemaphore(g_hSem, 1, NULL);

              if (!AbnormalTermination())

              {

                     // 控制流從__try塊正常退出,進入__finally

                     // 相關處理操作

              }

              else

              {

                     // 控制流從__try塊異常跳出,進入__finally

                     // 相關處理操作

              }

       }

       return dwTemp;

}

       通過AbnormalTermination函數可以判斷出,控制流是正常還是異常退出__try塊的,該函數由編譯器產生內聯代碼。異常退出包括__try塊中的代碼因含有return,goto,continue,break語句而“提前退出”造成“局部展開”,或者__try塊中的代碼存在非法內存訪問,或者其他異常導致“全局展開”等等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章