2009-09-28 37 views
7

爲了測試這個問題,我寫了一個最小化的Windows應用程序。如果我在WM_PAINT處理程序中強制訪問衝突,則此異常永遠不會到達調試器。如果在沒有調試器的情況下啓動,訪問衝突也不會顯示出來。通常你應該得到Windows錯誤報告對話框。WM_PAINT中的訪問衝突未被捕獲

深入挖掘看來,user32.dll中的某些內容會捕獲所有傳入的異常。這是正常的行爲嗎?我能以某種方式控制它嗎?沒有捕獲所有的例外安全風險?至少它是令人討厭的地獄。

這是在Vista 64上的32位和64位應用程序。在XP上,異常似乎按預期處理。其他Windows消息也有同樣的問題。也許他們都是?

WM_PAINT處理程序:

case WM_PAINT: 
    hdc = BeginPaint(hWnd, &ps); 
    *(int*)0 = 0; 
    EndPaint(hWnd, &ps); 
    break; 

回答

5

作爲解決方法,我刪除了我的窗口過程中的所有註冊的異常處理程序。相當醜陋。

 
LRESULT CALLBACK window_proc( 
    HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    // get thread information block 
    NT_TIB* tib; 
    __asm { 
     mov EAX, FS:[18h] 
     mov [tib], EAX 
    } 
    // old exception handler list 
    _EXCEPTION_REGISTRATION_RECORD* old_exception_handler = tib->ExceptionList; 
    // remove all exception handler with exception of the default handler 
    while(tib->ExceptionList->Next != (_EXCEPTION_REGISTRATION_RECORD*)-1) { 
     tib->ExceptionList = tib->ExceptionList->Next; 
    } 

    LRESULT result = DefWindowProc(hwnd, uMsg, wParam, lParam); 

    // restore old exception handler 
    tib->ExceptionList = old_exception_handler; 

    return result; 
} 
0

異常將在WinXP和Vista中被拋出。我剛剛在Vista中調試和發佈配置中進行了測試。新的Win32應用程序項目中是否存在相同的問題?

3

DispatchMessage似乎現在包含一個SEH try catch塊,它禁止window procs生成的異常。

您仍然可以在調試器中捕獲這些異常 - 根據您的visual studio版本,您需要打開調試 - >異常對話框,並勾選所有Win32異常的「中斷時拋出異常」列,或者至少異常0xc0000005

+0

我知道,但這只是一個解決方案,如果使用調試器。處理Windows消息時可能會拋出的所有其他異常是什麼?你有任何官方的(或非官方的)文件或推理的變化嗎? –

0

我注意到,當您啓用Aero(默認情況下在Vista中)時,調整窗口大小會導致創建許多多頁錯誤。這些並不是正常的虛擬內存需要分頁錯誤。我懷疑(儘管這只是一個理論),Aero將圖形輸出重定向到受保護的內存塊,並捕獲故障,以便知道桌面上需要重新組合可見表面的哪些位。也許這也是在吃其他的訪問違規。

+0

從Vista視頻內存開始虛擬化。這不應該與應用程序中的任何例外相關。至少啓用Aero或不會在Windows消息中修改異常處理。 –

+0

你說得對。無論是否啓用桌面合成,該例外均會丟失。 –

0

從XP開始,可以使用Vector Exception Handling功能。它優先於所有其他類型的例外。在我的例子中,它正確地捕獲了WM_PAINT消息中的訪問衝突。不幸的是,它還捕獲所有其他類型的異常,我應該通過檢查異常代碼來解決這些異常。