Analisi dump di arresto anomalo del sistema

Non tutti i bug possono essere trovati prima del rilascio, il che significa che non tutti i bug che generano eccezioni possono essere trovati prima del rilascio. Fortunatamente, Microsoft ha incluso in Platform SDK una funzione per aiutare gli sviluppatori a raccogliere informazioni sulle eccezioni individuate dagli utenti. La funzione MiniDumpWriteDump scrive le informazioni necessarie sul dump di arresto anomalo del sistema in un file senza salvare l'intero spazio del processo. Questo file di informazioni sul dump di arresto anomalo del sistema è denominato minidump. Questo articolo tecnico fornisce informazioni su come scrivere e usare un minidump.

Scrittura di un minidump

Le opzioni di base per la scrittura di un minidump sono le seguenti:

  • Non eseguire alcuna operazione. Windows genera automaticamente un minidump ogni volta che un programma genera un'eccezione non gestita. La generazione automatica di un minidump è disponibile a partire da Windows XP. Se l'utente lo consente, il minidump verrà inviato a Microsoft e non allo sviluppatore, tramite Segnalazione errori Windows (WER). Gli sviluppatori possono accedere a questi minidump tramite il programma applicazione desktop di Windows.

    L'uso di WER richiede:

    • Sviluppatori per firmare le applicazioni con Authenticode
    • Le applicazioni hanno una risorsa VERSIONINFO valida in ogni eseguibile e DLL

    Se si implementa una routine personalizzata per le eccezioni non gestite, è consigliabile usare la funzione ReportFault nel gestore eccezioni per inviare anche un minidump automatizzato a WER. La funzione ReportFault gestisce tutti i problemi di connessione e invio del minidump a WER. L'invio di minidump a WER viola i requisiti di Giochi per Windows.

    Per altre info su WER, vedi Segnalazione errori Windows.

  • Usare un prodotto di Microsoft Visual Studio Team System. Scegliere Salva dump con nome dal menu Debug per salvare una copia di un dump. L'uso di un dump salvato in locale è solo un'opzione per i test interni e il debug.

  • Aggiungere codice al progetto. Aggiungere la funzione MiniDumpWriteDump e il codice di gestione delle eccezioni appropriato per salvare e inviare un minidump direttamente allo sviluppatore. Questo articolo illustra come implementare questa opzione. Si noti tuttavia che MiniDumpWriteDump non funziona attualmente con codice gestito ed è disponibile solo in Windows XP, Windows Vista, Windows 7.

Thread safety

MiniDumpWriteDump fa parte della libreria DBGHELP. Questa libreria non è thread-safe, quindi qualsiasi programma che usa MiniDumpWriteDump deve sincronizzare tutti i thread prima di tentare di chiamare MiniDumpWriteDump.

Scrittura di un minidump con codice

L'implementazione effettiva è semplice. Di seguito è riportato un semplice esempio di come usare MiniDumpWriteDump.

#include <dbghelp.h>
#include <shellapi.h>
#include <shlobj.h>

int GenerateDump(EXCEPTION_POINTERS* pExceptionPointers)
{
    BOOL bMiniDumpSuccessful;
    WCHAR szPath[MAX_PATH]; 
    WCHAR szFileName[MAX_PATH]; 
    WCHAR* szAppName = L"AppName";
    WCHAR* szVersion = L"v1.0";
    DWORD dwBufferSize = MAX_PATH;
    HANDLE hDumpFile;
    SYSTEMTIME stLocalTime;
    MINIDUMP_EXCEPTION_INFORMATION ExpParam;

    GetLocalTime( &stLocalTime );
    GetTempPath( dwBufferSize, szPath );

    StringCchPrintf( szFileName, MAX_PATH, L"%s%s", szPath, szAppName );
    CreateDirectory( szFileName, NULL );

    StringCchPrintf( szFileName, MAX_PATH, L"%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", 
               szPath, szAppName, szVersion, 
               stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, 
               stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, 
               GetCurrentProcessId(), GetCurrentThreadId());
    hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, 
                FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);

    ExpParam.ThreadId = GetCurrentThreadId();
    ExpParam.ExceptionPointers = pExceptionPointers;
    ExpParam.ClientPointers = TRUE;

    bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), 
                    hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);

    return EXCEPTION_EXECUTE_HANDLER;
}


void SomeFunction()
{
    __try
    {
        int *pBadPtr = NULL;
        *pBadPtr = 0;
    }
    __except(GenerateDump(GetExceptionInformation()))
    {
    }
}

In questo esempio viene illustrato l'utilizzo di base di MiniDumpWriteDump e le informazioni minime necessarie per chiamarlo. Il nome del file di dump spetta allo sviluppatore; Tuttavia, per evitare conflitti di nomi di file, è consigliabile generare il nome file dal nome e dal numero di versione dell'applicazione, dall'ID di processo e thread e dalla data e dall'ora. Ciò consentirà anche di mantenere i minidump raggruppati per applicazione e versione. Spetta allo sviluppatore decidere la quantità di informazioni usate per distinguere i nomi di file minidump.

Si noti che il nome del percorso nell'esempio precedente è stato generato chiamando la funzione GetTempPath per recuperare il percorso della directory designata per i file temporanei. L'uso di questa directory funziona anche con account utente con privilegi minimi e impedisce anche al minidump di occupare spazio su disco rigido dopo che non è più necessario.

Se si archivia il prodotto durante il processo di compilazione giornaliero, assicurarsi anche di includere simboli per la compilazione in modo da poter eseguire il debug di una versione precedente del prodotto, se necessario. È anche necessario eseguire i passaggi per mantenere le ottimizzazioni complete del compilatore durante la generazione di simboli. A tale scopo, aprire le proprietà del progetto nell'ambiente di sviluppo e, per la configurazione della versione, eseguire le operazioni seguenti:

  1. Sul lato sinistro della pagina delle proprietà del progetto fare clic su C/C++. Per impostazione predefinita, vengono visualizzate le impostazioni Generali . Sul lato destro della pagina delle proprietà del progetto impostare Formato informazioni di debug su Database programma (/Zi).
  2. Sul lato sinistro della pagina delle proprietà espandere Linker e quindi fare clic su Debug. Sul lato destro della pagina delle proprietà impostare Genera informazioni di debug su Sì (/DEBUG).
  3. Fare clic su Ottimizzazione e impostare Riferimenti a E liminare dati senza riferimenti (/OPT:REF).Click Optimization, and set References to Eliminate Unreferenced Data (/OPT:REF).
  4. Impostare Enable COMDAT Folding (Abilita riduzione COMDAT) per rimuovere i COMDAT ridondanti (/OPT:ICF).Set Enable COMDAT Folding to Remove Redundant COMDATs (/OPT:ICF).

MSDN include informazioni più dettagliate sulla struttura MINIDUMP_EXCEPTION_INFORMATION e sulla funzione MiniDumpWriteDump.

Uso di Dumpchk.exe

Dumpchk.exe è un'utilità della riga di comando che può essere usata per verificare che un file di dump sia stato creato correttamente. Se Dumpchk.exe genera un errore, il file di dump è danneggiato e non può essere analizzato. Per informazioni sull'uso di Dumpchk.exe, vedere How to Use Dumpchk.exe to Check a Memory Dump File.

Dumpchk.exe è incluso nel CD del prodotto Windows XP e può essere installato in Unità di sistema\Programmi\Strumenti di supporto\ eseguendo Setup.exe nella cartella Support\Tools\ nel CD del prodotto Windows XP. Puoi anche ottenere la versione più recente di Dumpchk.exe scaricando e installando gli strumenti di debug disponibili in Strumenti di debug di Windows in Windows Hardware Developer Central.

Analisi di un minidump

L'apertura di un minidump per l'analisi è semplice come crearne una.

Per analizzare un minidump

  1. Aprire Visual Studio.
  2. Scegliere Apri progetto dal menu File.
  3. Impostare File di tiposu File di dump, passare al file di dump, selezionarlo e fare clic su Apri.
  4. Eseguire il debugger.

Il debugger creerà un processo simulato. Il processo simulato verrà interrotto all'istruzione che ha causato l'arresto anomalo.

Utilizzo del server dei simboli pubblici Microsoft

Per ottenere lo stack per arresti anomali a livello di driver o di sistema, potrebbe essere necessario configurare Visual Studio in modo che punti al server dei simboli pubblici Microsoft.

Per impostare un percorso sul server dei simboli Microsoft

  1. Scegliere Opzioni dal menu Debug.
  2. Nella finestra di dialogo Opzioni aprire il nodo Debug e fare clic su Simboli.
  3. Assicurarsi di cercare i percorsi precedenti solo quando i simboli vengono caricati manualmente non è selezionato, a meno che non si voglia caricare manualmente i simboli durante il debug.
  4. Se si usano simboli in un server di simboli remoto, è possibile migliorare le prestazioni specificando una directory locale in cui è possibile copiare i simboli. A tale scopo, immettere un percorso per i simboli della cache dal server dei simboli a questa directory. Per connettersi al server dei simboli pubblici Microsoft, è necessario abilitare questa impostazione. Si noti che se si esegue il debug di un programma in un computer remoto, la directory della cache fa riferimento a una directory nel computer remoto.
  5. Fare clic su OK.
  6. Poiché si usa il server dei simboli pubblici Microsoft, viene visualizzata una finestra di dialogo Contratto di licenza con l'utente finale. Fare clic su per accettare il contratto e scaricare i simboli nella cache locale.

Debug di un minidump con WinDbg

È anche possibile usare WinDbg, un debugger che fa parte degli strumenti di debug di Windows, per eseguire il debug di un minidump. WinDbg consente di eseguire il debug senza dover usare Visual Studio. Per scaricare Gli strumenti di debug di Windows, vedi Strumenti di debug di Windows in Windows Hardware Developer Central.

Dopo aver installato Gli strumenti di debug di Windows, è necessario immettere il percorso del simbolo in WinDbg.

Per immettere un percorso di simboli in WinDbg

  1. Scegliere Percorso simbolo dal menu File.

  2. Nella finestra Percorso di ricerca simboli immettere quanto segue:

    "srv\*c:\\cache\*https://msdl.microsoft.com/download/symbols;"

Uso di strumenti di protezione dalla copia con minidump

Gli sviluppatori devono anche essere consapevoli del modo in cui lo schema di protezione delle copie potrebbe influire sul minidump. La maggior parte degli schemi di protezione delle copie ha i propri strumenti di descramble e spetta allo sviluppatore imparare a usare questi strumenti con MiniDumpWriteDump.

Riepilogo

La funzione MiniDumpWriteDump può essere uno strumento estremamente utile per raccogliere e risolvere i bug dopo il rilascio del prodotto. La scrittura di un gestore eccezioni personalizzato che usa MiniDumpWriteDump consente allo sviluppatore di personalizzare la raccolta di informazioni e migliorare il processo di debug. La funzione è sufficientemente flessibile da usare in qualsiasi progetto basato su C++e deve essere considerata parte del processo di stabilità di qualsiasi progetto.