2010-03-02 10 views
7

Ho un cliente che sta ottenendo un crash riproducibile al 100% che non riesco a replicare nel mio programma compilato in Visual Studio 2005. Ho inviato loro una build di debug del mio programma e mantenuto a portata di mano tutti i file PDB e DLL. Mi hanno inviato il file minidump, ma quando lo apro ricevo:Debug di un minidump in Visual Studio in cui lo stack di chiamate è nullo

"Eccezione non gestita a 0x00000000 in MiniDump.dmp: 0xC0000005: posizione di lettura violazione violazione 0x00000000."

Quindi lo stack di chiamate mostra solo "0x00000000()" e lo smontaggio mostra un dump della memoria a 0x0. Ho impostato il server dei simboli, caricato i miei simboli PDB, ecc. Ma non riesco a vedere alcun modo per sapere quale delle molte DLL abbia effettivamente causato il salto nullo. Si tratta di un progetto di grandi dimensioni con molte dipendenze e alcuni di essi sono binari per i quali non dispongo dell'origine o dei PDB, poiché sto utilizzando un'API di terze parti.

Quindi, come mai questo minidump è utile? Come posso vedere quale DLL ha causato l'arresto anomalo? Non ho mai usato minidump per il debugging, ma tutte le esercitazioni che ho letto sembrano mostrare almeno un nome di funzione o qualcos'altro che ti dà un indizio nello stack di chiamate. Ho appena ottenuto la riga che punta a null.

Ho anche provato a utilizzare "Depends" per verificare se esistesse una dipendenza DLL non risolta; tuttavia sulle mie tre macchine di prova con vari sistemi operativi Windows, mi sembra di ottenere tre diversi set di dipendenze DLL OS (e tuttavia non è possibile replicare l'arresto anomalo); quindi questo non sembra un metodo particolarmente affidabile per diagnosticare il problema.

Quali altri metodi sono disponibili per determinare la causa di questo problema? C'è un modo per fare un passo indietro di un'istruzione per vedere quale DLL è saltata su null?

+2

ld ModuleName carica i simboli per un modulo. ! analyze -v ti darà una traccia dello stack. Tra questi due, dovresti avere abbastanza informazioni per iniziare. http://windbg.info/doc/1-common-cmds.html ha una lista di comandi WinDbg comuni. –

+0

Hai ragione Vanessa: stavo usando il debugger integrato in Visual Studio, ma quando uso WinDbg ottengo il nome del modulo. La lezione è qui: non utilizzare il debugger di Visual Studio per analizzare l'analisi post-mortem dello stack? – Piers

+0

Ogni volta che ho visto questo è stato causato chiamando un puntatore a funzione nulla. – paulm

risposta

2

L'idea alla base di tutti i "semplici" metodi di debug post mortem è l'acquisizione di una traccia di stack. Se l'applicazione sovrascrive lo stack, non c'è modo per tale analisi. Solo metodi molto sofisticati, che registrano l'intera esecuzione del programma in hardware dedicato, potrebbero aiutare.

La strada da percorrere in questo caso sono i file di registro. Distribuisci alcune dichiarazioni di registro molto ampie intorno all'area in cui si verifica l'errore e trasmetti quella versione al cliente. Dopo l'arresto verrà visualizzata l'ultima istruzione del registro nel file di registro. Aggiungere più istruzioni di registro tra quel punto e la successiva dichiarazione di registro che non è stata registrata nel file di registro, spedire di nuovo quella versione. Ripeti finché non trovi la linea che causa il problema.

ho scritto un articolo in due parti di questo a ddj.com:

About Log Files Part 1

About Log Files Part 2

0

Solo un'osservazione, ma la la pila sta ottenendo tronco o sopra-scritto, potrebbe essere questo un semplice caso di utilizzo di un campo non inizializzato o forse un sovraccarico del buffer?

Potrebbe essere abbastanza facile da individuare.

+0

Mi aspetto che il debugger di runtime lo catturi in questo caso. Il fatto che si blocca solo su circa il 10% dei computer mi fa pensare che il problema risieda altrove. – Piers

0

Hai provato a impostare WinDbg sul computer di un cliente e usarlo come debugger predefinito per qualsiasi applicazione che causa un arresto anomalo? Hai solo bisogno di aggiungere file pdb alla cartella in cui risiede la tua applicazione. Quando si verifica una cotta, WinDbg si avvia e puoi provare a ottenere lo stack delle chiamate.

0

Forse lo sapete già, ma qui ci sono alcuni punti sul debug di minidump: 1.È necessario avere esattamente gli stessi eseguibili e file PDB, come sul computer client in cui è stato creato il minidump, e devono essere posizionati esattamente nelle stesse directory. La semplice ricostruzione della stessa versione non aiuta. 2. Il debugger deve essere connesso al server MS Symbols. 3. All'avvio del debugger, stampa il log di caricamento del processo nella finestra Output. Generalmente, tutte le librerie dovrebbero essere caricate con successo con le informazioni di debug. Vengono caricate anche le librerie senza informazioni di debug, ma "nessuna informazione di debug" viene stampata. Impara questo registro: ti può dare alcune informazioni.

Se lo stack eseguibile contiene frame da una libreria senza informazioni di debug, potrebbe non essere visualizzato. Ciò accade, ad esempio, se il tuo codice è in esecuzione come callback di libreria di terze parti.

Prova a creare il minidump sul tuo computer, aggiungendo del codice che crea un'eccezione non gestita e esegui il debug immediatamente. funziona? Confronta il log di caricamento in sessioni di debug di successo e non riuscite.

+0

Nota aggiuntiva: come si crea il minidump nel codice? Confronta il tuo codice con questo esempio: http://www.codeproject.com/KB/debug/postmortemdebug_standalone1.aspx –

+0

In realtà l'applicazione host con cui sto lavorando sta scrivendo il minidump, quindi non ho il controllo diretto su questo processo . La maggior parte delle volte funziona, ma non sembra quando lo stack delle chiamate viene cancellato. – Piers

5

Bene, sembra che la risposta in questo caso sia stata "Usa WinDbg invece di Visual Studio per il debug di minidump". Non sono riuscito a ottenere informazioni utili su VS, ma WinDbg mi ha fornito una serie di informazioni sulla catena di chiamate alle funzioni che hanno portato al crash.

In questo caso non ha ancora aiutato a risolvere il mio problema, poiché tutte le funzioni erano nella libreria di terze parti che sto usando, quindi sembra che l'unica risposta definitiva al mio problema specifico sia l'uso di file di registro per Traccia lo stato della mia applicazione che porta al crash.

Suppongo che se qualcun altro vede un problema simile con uno stack di chiamate inutile durante il debug di un minidump, la procedura migliore è di aprirlo con WinDgb anziché Visual Studio. Sembra strano che lo strumento migliore per il lavoro sia il prodotto Microsoft gratuito, non quello commerciale.

L'altra lezione qui è probabilmente "qualsiasi programma che utilizza una libreria di terze parti ha bisogno di scrivere un file di registro".

0

È possibile che si sia chiamato puntatore a funzione nulla. Le informazioni sulla funzione di esecuzione corrente sono necessarie per mostrare le informazioni sullo stack di chiamata. Forza il puntatore dell'istruzione impostato per l'avvio di qualsiasi funzione semplice, quindi visualizzerai nuovamente le informazioni sullo stack di chiamata.

void SimpleFunc() 
{ // <- set next statement here 
} 
Problemi correlati