Absturzabbildanalyse

Nicht alle Fehler können vor der Veröffentlichung gefunden werden, was bedeutet, dass nicht alle Fehler, die Ausnahmen auslösen, vor der Veröffentlichung gefunden werden können. Glücklicherweise enthält Microsoft im Platform SDK eine Funktion, mit der Entwickler Informationen zu Ausnahmen sammeln können, die von Benutzern ermittelt werden. Die MiniDumpWriteDump-Funktion schreibt die erforderlichen Absturzabbildinformationen in eine Datei, ohne den gesamten Prozessbereich zu speichern. Diese Absturzabbild-Informationsdatei wird als Minidump bezeichnet. Dieser technische Artikel enthält Informationen zum Schreiben und Verwenden eines Minidumps.

Schreiben eines Minidumps

Die grundlegenden Optionen zum Schreiben eines Minidumps sind wie folgt:

  • Sie unternehmen nichts. Windows generiert automatisch einen Minidump, wenn ein Programm eine unbehandelte Ausnahme auslöst. Die automatische Generierung eines Minidumps ist seit Windows XP verfügbar. Wenn der Benutzer dies zulässt, wird der Minidump über Windows-Fehlerberichterstattung (WER) an Microsoft und nicht an den Entwickler gesendet. Entwickler können über das Windows-Desktopanwendungsprogramm Zugriff auf diese Minidumps erhalten.

    Die Verwendung von WER erfordert Folgendes:

    • Entwickler, um ihre Anwendungen mit Authenticode zu signieren
    • Anwendungen verfügen über gültige VERSIONINFO-Ressource in jeder ausführbaren Datei und DLL

    Wenn Sie eine benutzerdefinierte Routine für unbehandelte Ausnahmen implementieren, werden Sie dringend aufgefordert, die ReportFault-Funktion im Ausnahmehandler zu verwenden, um auch einen automatisierten Minidump an WER zu senden. Die ReportFault-Funktion behandelt alle Probleme beim Herstellen einer Verbindung mit und senden den Minidump an WER. Die Nichtübermittlung von Minidumps an WER verstößt gegen die Anforderungen von Games for Windows.

    Weitere Informationen über WER finden Sie unter Windows-Fehlerberichterstattung.

  • Verwenden Sie ein Produkt aus dem Microsoft Visual Studio Team System. Klicken Sie im Menü Debuggen auf Speicherabbild speichern unter, um eine Kopie eines Dumps zu speichern. Die Verwendung eines lokal gespeicherten Dumps ist nur eine Option zum internen Testen und Debuggen.

  • Fügen Sie Ihrem Projekt Code hinzu. Fügen Sie die MiniDumpWriteDump-Funktion und den entsprechenden Ausnahmebehandlungscode hinzu, um einen Minidump direkt an den Entwickler zu speichern und zu senden. In diesem Artikel wird die Implementierung dieser Option veranschaulicht. Beachten Sie jedoch, dass MiniDumpWriteDump derzeit nicht mit verwaltetem Code funktioniert und nur unter Windows XP, Windows Vista, Windows 7 verfügbar ist.

Threadsicherheit

MiniDumpWriteDump ist Teil der DBGHELP-Bibliothek. Diese Bibliothek ist nicht threadsicher, daher sollte jedes Programm, das MiniDumpWriteDump verwendet, alle Threads synchronisieren, bevor versucht wird, MiniDumpWriteDump aufzurufen.

Schreiben eines Minidumps mit Code

Die tatsächliche Implementierung ist einfach. Im Folgenden sehen Sie ein einfaches Beispiel für die Verwendung von 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 diesem Beispiel wird die grundlegende Verwendung von MiniDumpWriteDump und die minimalen Informationen veranschaulicht, die zum Aufrufen erforderlich sind. Der Name der Speicherabbilddatei liegt am Entwickler; Um Dateinamenkonflikte zu vermeiden, empfiehlt es sich jedoch, den Dateinamen aus dem Namen und der Versionsnummer der Anwendung, den Prozess- und Thread-IDs sowie das Datum und die Uhrzeit zu generieren. Dies hilft auch, die Minidumps nach Anwendung und Version zu gruppieren. Es liegt an dem Entwickler, zu entscheiden, wie viele Informationen verwendet werden, um Minidump-Dateinamen zu unterscheiden.

Beachten Sie, dass der Pfadname im vorherigen Beispiel durch Aufrufen der GetTempPath-Funktion generiert wurde, um den Pfad des Verzeichnisses abzurufen, das für temporäre Dateien bestimmt ist. Die Verwendung dieses Verzeichnisses funktioniert auch bei Benutzerkonten mit geringsten Rechten, und sie verhindert auch, dass der Minidump Festplattenspeicher einnimmt, nachdem er nicht mehr benötigt wird.

Wenn Sie das Produkt während des täglichen Build-Prozesses archivieren, sollten Sie auch Symbole für den Build enthalten, damit Sie bei Bedarf eine alte Version des Produkts debuggen können. Außerdem müssen Sie Schritte ausführen, um vollständige Compileroptimierungen beim Generieren von Symbolen aufrechtzuerhalten. Dazu können Sie die Eigenschaften Ihres Projekts in der Entwicklungsumgebung öffnen und für die Release-Konfiguration die folgenden Aktionen ausführen:

  1. Klicken Sie auf der linken Seite der Eigenschaftenseite des Projekts auf C/C++. Standardmäßig werden hier allgemeine Einstellungen angezeigt. Legen Sie auf der rechten Seite der Eigenschaftenseite des Projekts das Debug-Informationsformat auf die Programmdatenbank (/Zi) fest.
  2. Erweitern Sie auf der linken Seite der Eigenschaftenseite den Linker und klicken Sie dann auf Debuggen. Legen Sie auf der rechten Seite der Eigenschaftenseite Debug-Informationen generieren auf Ja (/DEBUG) fest.
  3. Klicken Sie auf Optimierung und legen Sie Verweise auf die Eliminierung nicht referenzierter Daten (/OPT:REF) fest.
  4. Legen Sie COMDAT-Faltung aktivieren fest, um redundante COMDATs (/OPT:ICF) zu entfernen.

Weitere Informationen finden Sie in der MINIDUMP_EXCEPTION_INFORMATION-Struktur und in der MiniDumpWriteDump-Funktion.

Verwenden von Dumpchk.exe

Dumpchk.exe ist ein Befehlszeilenprogramm, das verwendet werden kann, um zu überprüfen, ob eine Speicherabbilddatei ordnungsgemäß erstellt wurde. Wenn Dumpchk.exe einen Fehler generiert, ist die Speicherabbilddatei beschädigt und kann nicht analysiert werden. Informationen zur Verwendung von Dumpchk.exe finden Sie unter Verwendung von Dumpchk.exe zum Überprüfen einer Speicherabbilddatei.

Dumpchk.exe ist auf der Windows XP-Produkt-CD enthalten und kann auf System Drive\Programme\Supporttools\ installiert werden, indem sie Setup.exe im Ordner „Support\Tools\” auf der Windows XP-Produkt-CD ausführen. Sie können auch die neueste Version von Dumpchk.exe erhalten, indem Sie die Debug-Tools herunterladen und installieren, die unter Windows Debugging Tools unter Windows Hardware Developer Central verfügbar sind.

Analysieren eines Minidumps

Das Öffnen eines Minidumps für die Analyse ist so einfach wie das Erstellen eines.

So analysieren Sie einen Minidump

  1. Öffnen Sie Visual Studio.
  2. Klicken Sie im Menü Datei auf Projekt öffnen.
  3. Legen Sie Dateien vom Typ auf Dump-Dateien fest, navigieren Sie zur Speicherabbilddatei, wählen Sie sie aus, und klicken Sie auf Öffnen.
  4. Ausführen des Debuggers.

Der Debugger erstellt einen simulierten Prozess. Der simulierte Prozess wird an der Anweisung angehalten, die den Absturz verursacht hat.

Verwenden des öffentlichen Microsoft Symbolservers

Um den Stapel für Treiber- oder Systemabstürzen abzurufen, muss Visual Studio möglicherweise so konfiguriert werden, dass er auf den öffentlichen Symbolserver von Microsoft verweist.

So legen Sie einen Pfad zum Microsoft-Symbolserver fest

  1. Klicken Sie im Menü Debug auf Optionen.
  2. Öffnen Sie im Dialogfeld Optionen den Knoten Debuggen und klicken Sie auf Symbole.
  3. Stellen Sie sicher, dass die oben genannten Speicherorte nur dann durchsucht werden, wenn Symbole manuell geladen werden, es sei denn, Sie möchten Symbole beim Debuggen manuell laden.
  4. Wenn Sie Symbole auf einem Remotesymbolserver verwenden, können Sie die Leistung verbessern, indem Sie ein lokales Verzeichnis angeben, in das Symbole kopiert werden können. Geben Sie dazu einen Pfad für Cachesymbole vom Symbolserver zu diesem Verzeichnis ein. Um eine Verbindung mit dem öffentlichen Microsoft-Symbolserver herzustellen, müssen Sie diese Einstellung aktivieren. Beachten Sie, dass beim Debuggen eines Programms auf einem Remotecomputer das Cacheverzeichnis auf ein Verzeichnis auf dem Remotecomputer verweist.
  5. Klicken Sie auf OK.
  6. Da Sie den öffentlichen Symbolserver von Microsoft verwenden, wird ein Dialogfeld für endbenutzerbezogene Lizenzvereinbarungen angezeigt. Klicken Sie auf Ja, um die Vereinbarung zu akzeptieren und Symbole in Ihren lokalen Cache herunterzuladen.

Debuggen eines Minidumps mit WinDbg

Sie können auch WinDbg verwenden, einen Debugger, der Teil der Windows-Debugging-Tools ist, um einen Minidump zu debuggen. Mit WinDbg können Sie debuggen, ohne Visual Studio verwenden zu müssen. Informationen zum Herunterladen von Windows-Debugging-Tools finden Sie unter Windows Debugging Tools unter Windows Hardware Developer Central.

Nach der Installation der Windows-Debugging-Tools müssen Sie den Symbolpfad in WinDbg eingeben.

So geben Sie einen Symbolpfad in WinDbg ein

  1. Klicken Sie im Menü Datei auf den Symbolpfad.

  2. Geben Sie im Fenster Symbolsuchpfad Folgendes ein:

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

Verwenden von Kopierschutztools mit Minidumps

Entwickler müssen auch wissen, wie sich ihr Kopierschutzschema auf den Minidump auswirken kann. Die meisten Kopierschutzschemas verfügen über eigene Entschlüsselungs-Tools, und es liegt am Entwickler, zu erfahren, wie Sie diese Tools mit MiniDumpWriteDump verwenden.

Zusammenfassung

Die MiniDumpWriteDump-Funktion kann ein äußerst nützliches Tool beim Sammeln und Lösen von Fehlern sein, nachdem das Produkt veröffentlicht wurde. Das Schreiben eines benutzerdefinierten Ausnahmehandlers, der MiniDumpWriteDump verwendet, ermöglicht es dem Entwickler, die Informationssammlung anzupassen und den Debugging-Prozess zu verbessern. Die Funktion ist flexibel genug, um in jedem C++-basierten Projekt verwendet zu werden und sollte als Teil des Stabilitätsprozesses eines Projekts betrachtet werden.