2011-04-06 140 views
0

我有一個Visual Studio 2008 C++程序,其中程序包裝在__try/__except區塊中以捕獲任何SEH異常。異常過濾器會創建一個錯誤日誌,並向用戶提供有關如何提交缺陷報告的詳細說明。SEH錯誤報告

過濾器中的代碼是否需要封裝在另一個__try/__except塊中?如果不是,如果不是,會發生什麼?如果是這樣,那應該如何處理?

static int MyFilter(struct _EXCEPTION_POINTERS* ep) 
{ 
    /* 
    Code to log the exception information, and instruct the user 
    on how to submit a defect report. Should this be in another 
    __try/__except block? 
    */ 
    return EXCEPTION_EXECUTE_HANDLER; 
} 

int WINAPI _tWinMain(HINSTANCE hInstance, 
         HINSTANCE /*hPrevInstance*/, 
         LPTSTR lpstrCmdLine, 
         int nCmdShow) 
{ 
    int result = 0; 

    __try 
    { 
     result = Execute(hInstance, lpstrCmdLine, nCmdShow); 
    } 
    __except(MyFilter(GetExceptionInformation())) 
    { 
     // empty 
    } 

    return 0; 
} 

感謝, PaulH


編輯: 如果MyFilter引發了異常,然後我得到了一個無限循環的例外。所以,它看起來確實需要__try/__except處理。我看這樣做:

static int MyFilter(struct _EXCEPTION_POINTERS* ep) 
{ 
    __try 
    { 
     /* 
     Code to log the exception information, and instruct the user 
     on how to submit a defect report. 
     */ 

     // cause an exception 
     int x = 0, y = 1/x; 
    } 
    __except(EXCEPTION_EXECUTE_HANDLER) { /*empty*/ } 
    return EXCEPTION_EXECUTE_HANDLER; 
} 

在這種情況下,程序應該有一個異常終止和異常應傳遞到操作系統它來處理。那是對的嗎?

回答

0

如果在過濾器中引發異常,您將再次返回過濾器方法。您的異常將由同一個__except塊處理。
但是在過濾器方法中使用另一個__try __except塊沒有問題。
不幸的是,我不能給你任何這方面的參考。我只是嘗試了我自己,你也可以。只需迫使一個零分。
通常我不使用SEH,但是我幾次沒有在過濾方法中引發異常。但是當我找到這個時,我沒有在msdn中找到任何東西。

+0

如果'MyFilter'產生一個異常,那麼我進入一個無限的異常循環。 – PaulH 2011-04-06 17:27:13

+0

當然,如果它是相同的例外,你會。正如我所說,你將最終在同一個__except塊中再次調用你的過濾函數。如果過濾器在第一次拋出,它將在第二次拋出,依此類推。 – mkaes 2011-04-07 09:42:46

+0

我似乎記得,如果在異常回調中發生未處理的SEH異常,並且它未被捕獲,則將其視爲雙重故障,並且該進程被內核終止。 – Stewart 2011-04-07 10:52:04

0

在做這件事時,您需要注意很多事情。當SEH處理程序運行時,您的進程處於完全未知的狀態,您嘗試執行的一些操作可能會失敗。例如,如果異常是堆棧溢出,那麼您可以在這裏做的事情很少。如果你在這裏使用UI框架(MFC說),它可能會被破壞或處於不一致的狀態,因爲你的應用程序可能會在某些重要操作的中途崩潰。如果你的應用程序是多線程的,你需要知道當你進入這個過濾器時,那些其他線程仍然在運行,並且處理可能會很小心。

如果你真的需要這樣做,另一種方法是有一個看門狗進程來做到這一點。

+0

我們假設異常過濾器中的代碼完全是過濾器本地的(靜態),並且不再使用UI,而是使用':: MessageBox'。 Windows(和Windows Mobile)都有一個監視程序進程,但是我想讓我的應用程序有機會在Dr. Watson得到它之前記錄錯誤。 – PaulH 2011-04-06 17:34:38

+0

當然,這可能在大多數情況下都有效,但並不總是奏效。例如,MessageBox會創建一個對話框並在線程堆棧上運行模態消息循環。如果你的堆棧被燒燬,那將不起作用。另一個風險是,通過屏幕上的消息框等模態對話框,在線程中創建的窗口消息仍然被泵送,因此您的wndprocs仍然可能會被調用,這意味着即使您所做的每件事都能正常運行應用程序代碼在你的異常處理程序中是「靜態的」。解決這個問題並不是不可能的,但這很難。 – Stewart 2011-04-07 10:46:55

+0

既然你提到了Windows Mobile(你之前沒有提到過),那麼我建議的看門狗進程可能不是那麼好,因爲CE 5上有32個進程限制。服務或驅動程序可能會這樣做更有效,因爲如果過程限制是一個問題,服務和設備總是在運行。 – Stewart 2011-04-07 10:49:16