5

Ho un'applicazione basata su finestra di dialogo basata su MFC creata con MSVS2005. Ecco il mio problema passo dopo passo. Ho pulsante sulla mia finestra e corrispondente click-handler con codice come questo:OpenGL sopprime le eccezioni nell'applicazione basata su finestra di dialogo MFC

int* i = 0; 
*i = 3; 

Io corro versione di debug del programma e quando clicco sul pulsante, Visual Studio catture fuoco e avvisi "posizione di scrittura Violazione di accesso "Eccezione, il programma non può recuperare dall'errore e tutto ciò che posso fare è fermare il debug. E questo è il comportamento giusto.

Ora aggiungo un po 'di codice di inizializzazione OpenGL nel metodo 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); 

Naturalmente questo non è esattamente quello che faccio, è la versione semplificata del mio codice. Bene, ora le cose strane cominciano a succedere: tutte le inizializzazioni vanno bene, non ci sono errori in OnInitDialog(), ma quando clicco sul pulsante ... non viene lanciata alcuna eccezione. Non accade nulla. Affatto. Se si imposta un punto di interruzione su *i = 3; e si preme F11 su di esso, la funzione di gestione si arresta immediatamente e il focus viene restituito all'applicazione, che continua a funzionare correttamente. Posso fare nuovamente clic sul pulsante e succederà la stessa cosa.

Sembra che qualcuno abbia gestito un'eccezione di violazione di accesso e ha restituito silenziosamente l'esecuzione al ciclo di ricezione dei messaggi dell'applicazione principale.

Se commento la riga wglMakeCurrent(DC, hrc);, tutto funziona come prima, viene generata un'eccezione e Visual Studio lo rileva e mostra la finestra con messaggio di errore e il programma deve essere terminato in seguito.

Ho riscontrato questo problema in Windows 7 64-bit, NVIDIA GeForce 8800 con i driver più recenti (dell'11.01.2010) disponibili sul sito Web installato. Il mio collega ha Windows Vista a 32 bit e non ha problemi di questo tipo - viene generata un'eccezione e l'applicazione si blocca in entrambi i casi.

Beh, spero bravi ragazzi mi aiuteranno :)

PS Il problema in origine in cui è esposto sotto this argomento.

+0

Questo è divertente, ho avuto lo stesso problema di recente ... se si esegue il wrapping del codice di eccezioni in un blocco try-catch, verrà rilevata l'eccezione lì, ma se l'eccezione si propaga nel codice MFC sembra essere ingoiata. Immagino che una soluzione potenziale sia quella di usare i blocchi try-catch da soli. – AshleysBrain

+0

Posso confermare questo problema e ha a che fare con OpenGL su Windows Vista 64 bit e Windows 7 64 bit. Cercando la risposta da solo :) – ralphtheninja

+0

Questo sembra simile al mio problema: http://stackoverflow.com/questions/2622200/exceptions-silently-caught-by-windows-how-to-handle-manually –

risposta

3

Ok, ho trovato qualche informazione in più su questo. Nel mio caso è Windows 7 che installa KiUserCallbackExceptionHandler come gestore di eccezioni, prima di chiamare il mio WndProc e darmi il controllo di esecuzione. Questo è fatto da ntd! KiUserCallbackDispatcher. Sospetto che questa sia una misura di sicurezza presa da Microsoft per prevenire l'hacking in SEH.

La soluzione è di avvolgere wndproc (o hookproc) con un frame try/except in modo da poter rilevare l'eccezione prima di Windows.

Grazie a Skywing a http://www.nynaeve.net/

Abbiamo contattato nVidia su questo problema , ma dicono che non è il loro bug, ma piuttosto la Microsoft. Potrebbe dirmi come hai individuato il gestore delle eccezioni ? E hai alcune informazioni aggiuntive, ad es. alcuni feedback da Microsoft?

Ho utilizzato il comando "! Exchain" in WinDbg per ottenere queste informazioni.

+0

Abbiamo contattato nVidia riguardo a questo problema, ma dicono che non è il loro bug, ma piuttosto quello di Microsoft. Per favore, puoi dire come hai localizzato il gestore delle eccezioni? E hai alcune informazioni aggiuntive, ad es. alcuni feedback da Microsoft? – Mikhail

+0

SEH era la risposta più conveniente, quindi accetterò. – Mikhail

0

In primo luogo, entrambi i comportamenti sono corretti. Il dereferenziamento di un puntatore nullo è "comportamento non definito", non una violazione di accesso garantita.

Innanzitutto, verificare se questo è correlato al lancio di eccezioni o solo per accedere alla posizione di memoria zero (provare un'eccezione diversa).

Se si configura Visual Studio per interrompere le violazioni di accesso di primo impatto, si interrompe?

Chiama VirtualQuery (NULL, ...) prima e dopo glMakeCurrent e confronta. Forse i driver OpenGL nVidia VirtualAlloc pagina zero (una cattiva idea, ma non impossibile o illegale).

+0

Stesso comportamento per qualsiasi eccezioni, incluse quelle sollevate manualmente con l'operatore di lancio. Se configuro Visual Studio di fermarsi alle eccezioni di prima scelta, si interrompe. – Mikhail

+0

Sembra che un gestore di eccezioni vettori sia registrato e mangia l'eccezione. http://msdn.microsoft.com/en-us/library/ms681420(VS.85).aspx Interrompi all'eccezione di prima scelta, quindi avvia il single-stepping (assicurati di avere l'opzione "Just My Code "disabilitato in modo da poter scorrere le altre librerie). Probabilmente alcuni gestori restituiscono EXCEPTION_CONTINUE_EXECUTION anziché EXCEPTION_CONTINUE_SEARCH. –

+0

Risultati comparati di VirtualQuery (NULL, ...), i risultati sono gli stessi per le chiamate prima e dopo wglCreateContext(). – Mikhail

1

Invece di avvolgere il WndProc o agganciando tutti wndProcs, è possibile utilizzare Vectored gestione delle eccezioni:

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

+0

L'ho fatto e ha funzionato per me. – Brian

+0

Lo riprendo. Abbiamo dovuto annullare questo cambiamento perché era eccessivamente aggressivo. C'erano delle eccezioni che volevamo lasciare da sole e permettere di essere gestiti nel modo normale, ma non siamo riusciti a distinguerle dalle Violazioni di accesso e simili, che vogliamo arrestare. – Brian

+0

Ho una classe base per tutte le interfacce utente che sovrascrive WndProc con __try/__catch. Il gestore chiama quindi il reporter del crash nel rilascio, nel debug continua così possiamo eseguire il debug del crash. –

0

Ho trovato questa domanda quando stavo osservando un problema simile. Il nostro problema si è rivelato un consumo silenzioso di eccezioni durante l'esecuzione di un'applicazione a 32 bit su Windows a 64 bit.

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

C'è una correzione disponibile da Microsoft, anche se la distribuzione è un po 'difficile se si dispone di più piattaforme di destinazione:

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

Ecco un articolo sull'argomento che descrive il comportamento:

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

Questo thread in overflow dello stack descrive anche il problema che stavo riscontrando: Exceptions silently caught by Windows, how to handle manually?

Problemi correlati