2010-01-29 60 views
5

我有一個使用MSVS2005創建的MFC驅動的基於對話框的應用程序。這是我的問題一步一步來。我有我的對話和相應的點擊處理程序按鈕,這樣的代碼:OpenGL在MFC基於對話框的應用程序中抑制異常

int* i = 0; 
*i = 3; 

我正在運行的程序的調試版本,當我按一下按鈕,Visual Studio的捕撈重點和警報「訪問衝突寫入位置「例外,程序無法從錯誤中恢復,我所能做的就是停止調試。這是正確的行爲。

現在我添加一些OpenGL的初始化代碼在OnInitDialog()方法:

HDC DC = GetDC(GetSafeHwnd()); 
    static PIXELFORMATDESCRIPTOR pfd = 
    { 
     sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd 
     1, // version number 
     PFD_DRAW_TO_WINDOW | // support window 
     PFD_SUPPORT_OPENGL | // support OpenGL 
     PFD_DOUBLEBUFFER, // double buffered 
     PFD_TYPE_RGBA, // RGBA type 
     24, // 24-bit color depth 
     0, 0, 0, 0, 0, 0, // color bits ignored 
     0, // no alpha buffer 
     0, // shift bit ignored 
     0, // no accumulation buffer 
     0, 0, 0, 0, // accum bits ignored 
     32, // 32-bit z-buffer 
     0, // no stencil buffer 
     0, // no auxiliary buffer 
     PFD_MAIN_PLANE, // main layer 
     0, // reserved 
     0, 0, 0 // layer masks ignored 
    }; 

    int pixelformat = ChoosePixelFormat(DC, &pfd); 
    SetPixelFormat(DC, pixelformat, &pfd); 

    HGLRC hrc = wglCreateContext(DC); 
    ASSERT(hrc != NULL); 
    wglMakeCurrent(DC, hrc); 

當然,這不正是我做什麼,這是我的代碼的簡化版本。那麼現在奇怪的事情開始發生:所有的初始化都很好,在OnInitDialog()中沒有錯誤,但是當我點擊按鈕...沒有任何異常被拋出。什麼都沒發生。完全一樣。如果我在*i = 3;上設置了一個斷點並按下F11,處理函數立即停止,焦點返回到應用程序,繼續運行良好。我可以再次點擊按鈕,同樣的事情會發生。

看起來好像有人已經處理了發生訪問衝突的異常並默默地將執行返回到主應用程序的消息接收週期。

如果我評論行wglMakeCurrent(DC, hrc);,所有的工作都像以前一樣正常,拋出異常並且Visual Studio捕獲它並顯示帶有錯誤消息的窗口,並且之後程序必須終止。

我在安裝了網站的Windows 7 64位,NVIDIA GeForce 8800和最新驅動程序(11.01.2010)下遇到此問題。我的同事擁有32位的Windows Vista,並且沒有這樣的問題 - 在這兩種情況下都會拋出異常並導致應用程序崩潰。

好,希望好人能幫助我:)

PS的問題最初是在那裏下this主題貼。

+0

這很有趣,我最近有同樣的問題......如果你在一個try-catch塊包裝異常拋出代碼,它將捕獲異常那裏,但如果異常傳播到MFC代碼它似乎吞下了。我想一個潛在的解決方法是自己使用try-catch塊。 – AshleysBrain 2010-01-29 15:52:01

+0

我可以證實這個問題,它與Windows Vista 64位和Windows 7 64位上的OpenGL有關。尋找答案本人:) – ralphtheninja 2010-02-12 16:38:28

+0

這似乎類似於我的問題: http://stackoverflow.com/questions/2622200/exceptions-silently-caught-by-windows-how-to-handle-manually – 2010-04-12 13:25:32

回答

3

好吧,我發現了更多關於這方面的信息。在我的情況下,它是在調用我的WndProc並給予我執行控制之前安裝KiUserCallbackExceptionHandler作爲異常處理程序的Windows 7。這是通過ntdll!KiUserCallbackDispatcher完成的。我懷疑這是微軟採取的一項安全措施,以防止黑客入侵SEH。

解決方案是用一個try/except幀包裝你的wndproc(或者hookproc),這樣你可以在Windows之前捕獲異常。

感謝Skywing在http://www.nynaeve.net/

我們已經聯繫的nVidia這個 問題,但他們說,這不是他們的錯誤 ,而是微軟。請問 您可以告訴您如何找到 異常處理程序?你是否有 一些額外的信息,例如一些 來自微軟的反饋?

我在WinDbg中使用了「!exchain」命令來獲取這些信息。

+0

我們已經聯繫nVidia瞭解這個問題,但他們說這不是他們的錯誤,而是微軟的。你能告訴你如何找到異常處理程序嗎?並且您是否還有其他信息,例如一些來自微軟的反饋? – Mikhail 2010-05-25 14:39:41

+0

SEH是最方便的答案,所以我會接受它。 – Mikhail 2012-03-15 16:51:45

0

首先,這兩種行爲都是正確的。解引用空指針是「未定義的行爲」,而不是保證的訪問衝突。首先,找出這是與異常拋出還是僅與訪問內存位置零(嘗試不同的異常)相關。

如果您將Visual Studio配置爲停止一次訪問衝突,它會中斷嗎?

在glMakeCurrent之前和之後調用VirtualQuery(NULL,...)並進行比較。也許nVidia OpenGL驅動程序VirtualAlloc頁面爲零(一個糟糕的主意,但不是不可能的或非法的)。

+0

相同的行爲任何異常,包括用throw操作符手動引發。如果我將Visual Studio配置爲停止一次性異常,則會中斷。 – Mikhail 2010-02-16 09:07:50

+0

聲音像一個向量異常處理程序被註冊並吃掉異常。 http://msdn.microsoft.com/en-us/library/ms681420(VS.85).aspx 打破第一次機會的例外,然後開始單步(確保您有選項「只是我的代碼「禁用,以便您可以瀏覽其他庫)。可能某個處理程序返回EXCEPTION_CONTINUE_EXECUTION而不是EXCEPTION_CONTINUE_SEARCH。 – 2010-02-17 21:59:52

+0

VirtualQuery(NULL,...)的比較結果,對於wglCreateContext()之前和之後的調用,結果相同。 – Mikhail 2010-02-18 06:49:33

1

而不是包裹的WndProc或鉤住所有WndProcs,你可以使用向量異常處理:

http://msdn.microsoft.com/en-us/library/ms679274.aspx

+0

我做到了這一點,它爲我工作。 – Brian 2011-12-06 22:56:53

+0

我收回。我們不得不恢復這一改變,因爲它過於激進。有一些例外,我們想單獨留下,並允許以正常方式處理,但我們無法將它們與我們想要崩潰的訪問違規等相區分。 – Brian 2011-12-17 02:15:58

+0

我有一個用__try/__catch覆蓋WndProc的所有用戶界面的基類。處理程序然後在發佈中調用崩潰記錄器,在調試中繼續,以便我們可以調試崩潰。 – 2011-12-18 19:58:31

0

我在查看類似問題時發現此問題。在64位Windows上運行32位應用程序時,我們的問題證明是無意中使用異常。

http://connect.microsoft.com/VisualStudio/feedback/details/550944/hardware-exceptions-on-x64-machines-are-silently-caught-in-wndproc-messages

有可從Microsoft修復,雖然部署它是有點挑戰,如果你有多個目標平臺:

http://support.microsoft.com/kb/976038

下面是關於這個問題的描述行爲的文章:

http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/

在堆棧溢出此線程還介紹我遇到的問題: Exceptions silently caught by Windows, how to handle manually?

相關問題