2009-10-12 13 views
11

Ho usato minidump su molti progetti di gioco nel corso degli anni e sembrano avere circa il 50% di possibilità di avere uno stack di chiamate valido. Cosa posso fare per renderli migliori stack di chiamate?Perché i Minidump non danno buoni stack di chiamate?

Ho provato a inserire l'ultimo dbghelp.dll nella directory exe. Questo sembra aiutare alcuni.

Visual Studio 2008 o 2010 è migliore? (Sono ancora su VS 2005).

Il codice che utilizzo assomiglia allo this sample.

risposta

6

Cosa manca nel tuo callstack? Hai un gruppo di indirizzi che non risolvono nomi di funzioni validi (ad es. 0x8732ae00 invece di CFoo: Bar())? In questo caso, ciò che ti serve è mettere i tuoi .PDB dove il tuo debugger può trovarli, oppure impostare uno symbol server e impostare i "Percorsi dei simboli" nel menu contestuale del tasto destro del pannello Moduli.

Memorizziamo ogni .PDB da ogni binario ogni volta che qualcuno controlla un nuovo elenco di modifiche di Perforce, in modo che quando una discarica ritorna da qualcuno all'interno dell'ufficio o da qualsiasi cliente al dettaglio, abbiamo il .PDB corrispondente alla versione di il gioco che stavano correndo. Con il symbol server e i percorsi impostati, tutto quello che devo fare è semplicemente fare doppio clic su .mdmp e funziona sempre.

O si dispone di uno stack di chiamate che sembra avere solo una funzione al suo interno? Come, 0x8538cf00 senza nient'altro sopra nello stack? Se è così, allora il crash è in realtà lo stack stesso corrotto. Se gli indirizzi di ritorno nel backchain sono stati sovrascritti, naturalmente il debugger non sarà in grado di risolverli.

A volte si scopre anche che il thread che effettivamente emette il minidump non è quello che ha generato l'eccezione che ha causato l'arresto. Cerca nella finestra Thread per vedere se uno degli altri thread contiene il codice incriminato.

Se si esegue il debug di una build "Release", ovvero una compilata con tutte le flag di ottimizzazione attivate, si dovrà tener presente che il debugger avrà problemi a trovare variabili locali e altre dati. Questo perché attivare le ottimizzazioni significa consentire al compilatore di conservare i dati nei registri, ridurre i calcoli e, in generale, eseguire una serie di operazioni che impediscono la scrittura dei dati nello stack. Se questo è il tuo problema, allora dovrai aprire la finestra di smontaggio e inseguire i dati a mano, o ricostruire un binario di debug e riprodurre il problema dove puoi guardarlo.

+0

0x8732ae00 è un indirizzo improbabile, è nello spazio del kernel (con l'installazione da 2 GB di x86-32). Gli indirizzi 0x7_______ sono più comuni, poiché la DLL di Windows si adatta al limite di 2 GB. Questo riduce il numero di rilocazioni necessarie. Se non vedi simboli per loro, usa il _Microsoft_ Symbol Server. – MSalters

+1

Stavo solo inserendo gli indirizzi a caso, ad esempio (in questo caso è lì che una particolare console set-top piace spostare le DLL in modalità utente). – Crashworks

0

Non uso minidumps, ma piuttosto discarica teh stack "mano" in un file di log (vedi www.ddj.com/cpp/185300443 e How to Log Stack Frames with Windows x64).

Ho riscontrato un comportamento simile come quello che fai tu: a volte c'è uno stack di chiamate valido, a volte non c'è. In un numero minore di casi, lo stack potrebbe essere realmente danneggiato. In forse 1/3 di tutti i casi il gestore di eccezioni installato non viene chiamato affatto! Suppongo che sia in qualche modo un problema della gestione delle eccezioni strutturata di Windows.

4

Disattiva Ottimizzazione puntatore telaio, se sono necessari dump di stack. I frame pointer sono utilizzati per definire esplicitamente i fotogrammi stack. Senza di loro, il debugger deve dedurre la posizione di ciascun frame.

+0

Questa è una buona idea. Con i PDB e le DLL originali, tuttavia, il debugger di MSVC è in grado di elaborare comunque i frame stack con FPO, ma ovviamente il suo compito diventa molto più difficile. Lo so perché lo compiliamo con l'FPO e tengo sempre gli stack di minidump. – Crashworks

+0

Ovviamente è facile se il "crash" è dovuto a un breakpoint INT 3 manuale. Il problema è che la maggior parte degli arresti anomali non si verificano esattamente con l'istruzione buggy. La CPU si inciampa per un po ', fino a quando non viene attivato un errore. Nel frattempo, il codice eseguito non funziona come previsto e potrebbe corrompere lo stato dei programmi piuttosto un po '. Questo può includere istruzioni di esecuzione che non intendevi eseguire (particolare cattiveria: salti indiretti tramite un vtable mal interpretato). vtablecourse – MSalters

+1

Sì, l'assenza di indicatori di virata rende sicuramente molto più difficile il compito di pescare di nuovo attraverso lo stack. Anche se il programma è morto saltando attraverso un puntatore vfunc selvaggio, di solito si può capire da dove viene perché la CALL op spinge IP nello stack, ma trovarlo e poi lavorare dove sono andati tutti gli abitanti del posto può diventare un esercizio arduo nel lavorare all'indietro un op alla volta. Se ti trovi su questo torrente, windbg ha l'utile comando 'dps' che cerca nella memoria i simboli e gli indirizzi delle funzioni probabilmente conosciuti; ciò può aiutarti a cercare il vecchio EIP. – Crashworks

19

Una cosa che puoi fare per migliorare l'accuratezza degli stack di chiamate trovati nei dump è usare un debugger diverso da Visual Studio - in particolare, usa WinDbg o un altro strumento che usa il motore di debug "Windows Debugger" trovato in dbgeng. dll (al contrario del motore di debug di "Visual Studio Debugger" utilizzato da Visual Studio).

In base alla nostra esperienza, WinDbg è affidabile al 100% nella produzione di buoni stack di chiamate dalle stesse discariche in cui Visual Studio produce stack di chiamate inutilizzabili o estremamente imprecisi. Da quello che posso dire, nei casi in cui un'eccezione non gestita è la fonte del crash WinDbg esegue automaticamente il tricky process of reconstructing/recovering the exception callstack, ma Visual Studio non (o non può?). I due debugger utilizzano different heuristics for interpreting stacks

WinDbg può essere scoraggiante in un primo momento, quindi ecco la mia guida rapida su come rendere più facile o addirittura evitare di doverlo utilizzare direttamente.

Una di Mortal guida Mere Per Estrazione buon stack di chiamate

Questi sono ordinate da "più veloce/semplice" a "più lento/più criptico da interpretare".

  1. più semplice opzione: usare DbgDiag from Microsoft

    Questo è uno strumento poco conosciuto che consente di automatizzare un sacco di analisi dei problemi comuni, ed è abbastanza semplice per dare ai non programmatori o anche i clienti. È veloce e quasi infallibile, ed è diventato il mio strumento "go to" per analizzare rapidamente un crash dump in arrivo.

    • Avviare l'applicazione
    • "Analisi DebugDiag" Selezionare la casella di controllo "CrashHangAnalysis" sulla pagina principale
    • drag-and-drop di discarica in "File di dati" riquadro sulla pagina principale
    • Fai clic su "analisi Start"


    Dopo pochi secondi a pochi minuti si sputerà fuori un bel .mhtml contenente un'analisi del problema, informazioni su tutti i filo correlato, stack di chiamate completo s, ecc. Tutti i collegamenti ipertestuali e facili da usare.

    DebugDiag automatizza anche alcune delle più complicate analisi possibili ma dolorose in WinDbg (come rintracciare quale dei 350 thread dell'applicazione è responsabile di un deadlock).

    Nota: Chrome non scarica o apre i file .mhtml per motivi di sicurezza, quindi è necessario aprire in Internet Explorer o Microsoft Edge affinché sia ​​utilizzabile. Questo è fastidioso, e ho presentato una richiesta con il team DebugDiag ([email protected]) per modificare il formato di semplice HTML

  2. opzione Medio: Installare WinDbg come motore di debug alternativo per Visual Studio

    • Installare Visual Studio se non è ancora installato. Questo deve essere fatto prima del prossimo passo.
    • Installare il Windows Driver Kit (WDK)
    • lancio di Visual Studio, e (questa parte è importante!) Utilizzare il nuovo "File -> Apri -> Crash Dump ..." per aprire la discarica. Verrà eseguito il debug del dump di arresto anomalo del sistema utilizzando Windows Debugger (se invece si trascina il dump su Visual Studio o si utilizza l'opzione standard "File -> Apri -> File ..." per aprire il dump, verrà eseguito il debug utilizza il vecchio motore di debug di Visual Studio ...quindi fai attenzione a usare l'opzione giusta).
    • Ora dovresti essere in grado di vedere lo stack di chiamate corretto e navigare usando la GUI di Visual Studio, anche se alcune cose funzionano in modo diverso (le finestre di controllo richiedono l'uso della sintassi WinDbg non familiare, gli ID dei thread sono diversi, ecc.). Nota: l'interfaccia utente di Visual Studio può essere molto lenta, soprattutto se sono coinvolti molti thread e le finestre "threads" o "stack paralleli" sono aperte.
  3. opzione Hardcore: Utilizzare WinDbg direttamente

    • lancio WinDbg.exe
    • drag-and-drop di discarica nella finestra WinDbg
    • Tipo !analyze -v e premere Invio. Dopo un po 'di tempo WinDbg sputerà uno stack di chiamate in crash e anche la sua stima di quale sia la fonte del problema. Se stai analizzando un deadlock, puoi provare !analyze -v -hang e WinDbg ti mostrerà spesso la catena di dipendenze in questione.


    A questo punto è possibile avere tutte le informazioni necessarie! Tuttavia, se poi si desidera esaminare lo stato del processo nel debugger di Visual Studio è possibile prendere le ulteriori seguenti fasi:

    • Aprire il crash dump in Visual Studio
    • destro del mouse nella finestra di stack e scegliere "Vai a Disassemblaggio"
    • Incollare l'indirizzo esadecimale dalla riga superiore del callstack di output di WinDbg nella barra "Indirizzo" della finestra Smontaggio e premere invio. Ora sei nella posizione del crash, guardando il codice smontato.
    • Fare clic con il tasto destro del mouse nella finestra di disassemblaggio e scegliere "Vai al codice sorgente" per andare al codice sorgente per la posizione. Ora stai guardando il codice sorgente sul sito dello schianto.

Nota: tutto quanto sopra necessita di avere percorsi di server corretto di simboli configurati, altrimenti non sarà in grado di risolvere i simboli nei stack di chiamate. Raccomando di impostare _NT_SYMBOL_PATH environment variable in modo che sia automaticamente disponibile per Visual Studio, WinDbg e DebugDiag.

+0

Un'altra nota: per ottenere un'esperienza di debug * molto * più piacevole con i dump di arresto in modalità rilascio, c'è uno speciale flag del compilatore che inietta informazioni aggiuntive nei tuoi PDB, consentendo di scorrere correttamente il codice ottimizzato e vedere le funzioni integrate nella chiamata stack (e tracce di profiler!). Questo era disponibile come flag non documentato "/ d2Zi +" in VS2010 e poi modificato in flag ufficiale "/ Zo" in VS2013 Update 3. Per ulteriori informazioni, vedere http://randomascii.wordpress.com/2013/09/11/ debugging ottimizzato-codenew-in-visual-studio-2012 / –

1

È improbabile che il codice per registrare il minidump sia pertinente. Le cose principali che i record minidump sono le informazioni sul modulo (per ottenere simboli) e il contenuto completo di tutti gli stack di thread. Oltre a quelle informazioni di base (che sono sempre registrate) non importa nient'altro.

Ottenere buoni simboli (inclusi file PE) è cruciale per la camminata in pila. Maggiori dettagli possono essere trovati qui: https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/

Trovo che Visual Studio sia solitamente affidabile nella visualizzazione delle pile di chiamate. Visualizza automaticamente lo stack di chiamate relativo dal record di eccezioni e semplifica la modifica dei thread in modo che sia possibile visualizzare le pile di chiamate di tutti i thread. A volte prova a "nascondere" i dettagli che pensa possano confondervi - che ciò sia positivo o negativo dipende dal tuo livello di abilità.

Windbg consente di visualizzare lo stack di chiamate del codice che ha registrato il crash dump anziché lo stack di chiamate in blocco. Windbg richiede che tu vada ".ecxr "o"! analizza -v "per vedere lo stack anomalo trovo fastidioso: Windbg richiede anche più configurazioni per essere utile

I due debugger hanno euristiche di stack differenti. necessario, ad esempio, se si chiama o si torna all'indirizzo zero poiché non ci sono informazioni di svolgimento per quell'indirizzo.Per i crash "puliti" in cui l'istruzione errata è nel codice normale queste euristiche sono meno importanti

quasi certamente migliorato negli ultimi dieci anni: VS 2015 Community Edition è molto capace ed è gratuito, quindi puoi anche provarlo.

Se usi windbg puoi provare s Esperimenti Ome:

!vc7fpo - toggles some of the windbg heuristics. 
!stackdbg d, 7, f - turns on windbg stack walk 
k1 - walks one level of the stack, spitting diagnostics as controlled by !stackdbg 
dds esp - dumps the raw contents of the stack, doing a symbol lookup on each pointer 

Se l'aggiornamento a VS 2015 e avere ancora problemi, allora è probabile che la pila camminare fallimenti sono specifici per il crash che si sta vedendo. Se un sovraccarico del buffer trompa lo stack prima di bloccarsi, lo stack di chiamate verrà danneggiato in modo irreversibile. La tua domanda ha troppe poche informazioni su quali guasti stai vedendo per dare una diagnosi definitiva. Trovo abbastanza affidabile la visualizzazione dello stack di entrambi i debugger, ma di solito capisco anche perché a volte falliscono e quando ciò accade posso comunque estrarre le informazioni di cui ho bisogno.