2014-10-20 13 views
5

Ho aggiunto una funzione di mini-core-dump (tramite __try/__ except e MiniDumpWriteDump()) alla build di Windows della mia applicazione Qt, in modo che se/quando la mia applicazione si arresta mai, verrà scritto un file .dmp su disco per me per guardare e fare il debug con in seguito.Qual è il modo migliore per bloccare intenzionalmente la mia applicazione Windows?

Questo funziona abbastanza bene, ma per i test mi piacerebbe avere un metodo affidabile per rendere il mio programma in crash. Ad esempio, potrebbe esserci un pulsante "crash now" nella GUI e quando l'utente fa clic, causerà l'arresto intenzionale dell'applicazione.

Un modo per farlo, naturalmente, è come questo:

int * badPointer = NULL; 
*badPointer = 666; 

E che funziona per me, ma non mi piace questo approccio perché si basa su un comportamento indefinito - in particolare, la Lo standard C++ non richiede il codice sopra riportato per causare un arresto anomalo, quindi è possibile (da un punto di vista del giurista) che alcune versioni future del compilatore non si blocchino quando viene eseguito il codice precedente.

Come un approccio più "ufficiale", ho provato questo:

abort(); 

... che non termina il programma, ma non causa l'eccezione strutturata di Windows che fa scattare il gestore MiniCrashDump, in modo che nessun il file .dmp viene scritto.

La mia domanda è, esiste un "modo giusto ufficiale" per bloccare il programma? Vedo che l'API di Windows ha una funzione RaiseException() che potrei chiamare, ma non sono sicuro di quali dovrebbero essere gli argomenti appropriati. È questa la strada da percorrere, o c'è qualche chiamata più specifica che sarebbe meglio usare?

+0

Martello attraverso lo schermo. –

+1

Stai utilizzando parole chiave e comportamenti molto specifici per l'implementazione e sei preoccupato che cosa potrebbe dire una specifica C++ un giorno? Certo, RaiseException() è la via ufficiale. –

+0

@HansPassant Non è la specifica C++ che mi preoccupa tanto quanto l'ottimizzatore MSVC, che potrebbe iniziare a fare trucchi mentali in stile gcc come dire "poiché so che malePointer è NULL, e dal momento che il dereferenziamento di un puntatore NULL è un comportamento indefinito, posso ottimizza quello che scrivi "... e poi improvvisamente il mio pulsante di arresto non si arresta più. :) –

risposta

3

È perfettamente possibile disabilitare un puntatore nullo per causare una violazione di accesso se si sa che si sta utilizzando Windows - Windows offre maggiori garanzie rispetto al linguaggio C++. C++ dice che il dereferenziamento di un puntatore nullo è Undefined Behavior, ma Windows lo definisce come una violazione di accesso (che è perfettamente accettabile per quanto riguarda C++, dal momento che una violazione di accesso è un possibile risultato di Undefined Behavior).

Da Managing Virtual Memory:

Windows NT costruisce una salvaguardia nello spazio di indirizzi di ogni processo. Entrambi i 65.536 byte superiori e inferiori di ogni processo sono riservati in modo permanente dal sistema. Queste porzioni dello spazio di indirizzi sono riservati per intrappolare randagi puntatori puntatori che tentano di indirizzare la memoria nell'intervallo 00000000 -0000FFFF o 7FFF0000 -7FFFFFFF . Non a caso, è facile rilevare i puntatori in questo intervallo semplicemente ignorando i quattro nibbles inferiori (i due byte più a destra) in questi indirizzi. In sostanza, un puntatore non è valido se i quattro primi quattro sono 0000 o 7FFF ; tutti gli altri valori rappresentano indirizzi validi.

La prima pagina della memoria è sempre mappato come PAGE_NOACCESS, quindi se si tenta di leggere o scrivere un puntatore nullo (o qualsiasi puntatore all'interno +/- 64 KB di un puntatore nullo), sarai sempre rilanci un'eccezione di violazione di accesso.