Absturz-Dumps mit WinDbg + SOS lesen — Ein praxistauglicher Leitfaden zur Analyse nach der Sammlung

· · WinDbg, SOS, Absturz-Dump, .NET, CSharp, Debugging, PDB, Fehleruntersuchung, Technische Beratung

Ein früherer Artikel, „Eine Einführung in das Sammeln von Windows-Absturz-Dumps“, arbeitete das Sammeln von Dumps mit WER LocalDumps, ProcDump und MiniDumpWriteDump durch. Aber ein Dump, der lediglich gesammelt wurde, sagt Ihnen von sich aus gar nichts. Er wird erst dann zu nützlichem Material für eine Untersuchung, wenn Sie sich tatsächlich die Hände schmutzig machen und herausfinden, welcher Thread abgestürzt ist, warum er abgestürzt ist oder was Speicher festhält.

Dieser Artikel setzt dort an, wo der Sammel-Artikel aufgehört hat, und konzentriert sich eng auf das tatsächliche Lesen eines gesammelten Dumps mit WinDbg und der SOS-Erweiterung. Er behandelt Installation und Symbolkonfiguration, das Laden der für .NET-Anwendungen unerlässlichen SOS-Erweiterung, was man mit repräsentativen Befehlen wie !clrstack und !dumpheap -stat betrachtet und wie man es beurteilt, !analyze -v für native Abstürze, sowie wann man statt WinDbg zu dotnet-dump analyze greift.

1. Die Kurzfassung zuerst

  • Das Hauptwerkzeug für die Dump-Analyse ist WinDbg (die aktuelle Version, früher WinDbg Preview genannt). Sie erhalten es über winget install Microsoft.WinDbg oder aus dem Microsoft Store, und es läuft auf x64/ARM64 für Windows 10 Anniversary Update (1607) und höher sowie Windows 11.1
  • !clrstack, !dumpheap -stat, !gcroot und ähnliche Befehle arbeiten direkt mit CLR-Metadaten und Heap-Daten, sodass sie auch ohne geladene Symbole (PDBs) funktionieren. Was verloren geht, sind Quelldateinamen/Zeilennummern für verwalteten Code sowie Symbolnamen für native Frames. Möchten Sie die Dinge jedoch bis zur Quellzeile zurückverfolgen, ist das eine andere Sache, und die übliche Praxis ist, _NT_SYMBOL_PATH sowohl auf Microsofts öffentlichen Symbolserver als auch auf den Speicherort Ihrer eigenen PDBs zu richten.2
  • Für Dumps von .NET-Anwendungen (Framework / Core / 5+) werden verwaltete Informationen erst sichtbar, sobald Sie die SOS-Erweiterung laden. Mit dem nativen Befehl k (Stapelanzeige) allein lässt sich C#-Code nicht nachverfolgen.3
  • Es gibt drei repräsentative Untersuchungsmuster: Ist es bei einer Ausnahme abgestürzt, beginnen Sie mit !clrstack!pe; wächst der Speicher stetig, beginnen Sie mit !dumpheap -stat!gcroot; bei einem nativen Absturz beginnen Sie mit !analyze -v.
  • dotnet-dump analyze ist eine Option, wenn Sie WinDbg überspringen möchten. Die meisten SOS-Befehle funktionieren unverändert, aber es kann keine nativen Stack-Frames verarbeiten. Für rein verwaltete Untersuchungen ohne native DLLs oder COM ist es eine leichter einzurichtende Option.4
  • Die hier beschriebenen Verfahren betreffen das Lesen eines Dumps, nicht das Sammeln eines solchen. Wie Dumps gesammelt werden (WER / ProcDump / MiniDumpWriteDump), erfahren Sie im Sammel-Artikel; zum Entwerfen Ihrer Absturz-Konfiguration, sodass Protokolle und Dumps zusammenpassen, siehe „Aufbewahrung von Protokollen und Dumps bei Windows-App-Abstürzen gestalten“.

2. WinDbg installieren und Symbole konfigurieren

2.1 Installation

Die aktuelle Version von WinDbg lässt sich auf zwei Wegen installieren.1

winget install Microsoft.WinDbg

Die Installation über den Microsoft Store liefert dieselbe Engine, mit identischen Befehlen, Erweiterungen und Arbeitsabläufen. Nach der Installation aktualisiert es sich automatisch (im Hintergrund bei Store-/Direktinstallationen, oder über winget upgrade Microsoft.WinDbg bei der winget-Installation), sodass Sie kaum mit Verhaltensunterschieden zwischen Versionen zu kämpfen haben.1

2.2 Einen Dump öffnen

windbg -z C:\CrashDumps\MyApp\MyApp_20260702_101500.dmp

-z ist die Option, die eine beim Start zu öffnende Dump-Datei angibt. Dasselbe lässt sich aus der GUI über „Datei > Dump-Datei öffnen“ erledigen.

2.3 Den Symbolpfad konfigurieren

Wo der Windows-Debugger nach Symboldateien (PDBs) sucht, wird durch die Umgebungsvariable _NT_SYMBOL_PATH oder den Befehl .sympath innerhalb einer Sitzung gesteuert.2 In der Praxis besteht der übliche Ansatz darin, ihn sowohl auf Microsofts öffentlichen Symbolserver als auch auf den Speicherort Ihrer eigenen PDBs zu richten.

.symfix C:\Symbols\Microsoft
.sympath+ C:\Symbols\MyApp
.reload
  • .symfix ist eine Abkürzung, die den Pfad zu Microsofts öffentlichem Symbolserver (https://msdl.microsoft.com/download/symbols) zusammen mit einem angegebenen lokalen Cache setzt. Symbole für Standard-OS-DLLs werden automatisch von hier heruntergeladen.5
  • .sympath+ hängt den Speicherort Ihrer eigenen PDBs an den vorhandenen Pfad an. PDBs für Ihren eigenen Code müssen Sie selbst bereitstellen – sie sind nicht auf Microsofts Symbolserver gehostet.
  • .reload lädt neu und lässt Sie den Symbolstatus in der Modulliste prüfen.

Um dies dauerhaft über eine Umgebungsvariable zu setzen, verwenden Sie die folgende Form. Das eignet sich besser für automatisierte Analyse auf CI- oder Build-Servern.

set _NT_SYMBOL_PATH=srv*C:\Symbols\Microsoft*https://msdl.microsoft.com/download/symbols;C:\Symbols\MyApp

Um zu bestätigen, dass Symbole korrekt gelesen werden, listen Sie geladene Module mit dem Befehl lm (loaded modules) auf und prüfen Sie, ob das Zielmodul pdb symbols anzeigt. Steht dort noch deferred, sind die Symbole noch nicht aufgelöst.

3. Die SOS-Erweiterung laden

Für Dumps von .NET-Anwendungen können native WinDbg-Befehle allein Ihnen nicht den Inhalt des verwalteten Heaps, C#-Stack-Frames oder den Inhalt von Ausnahmeobjekten zeigen. Diese Lücke füllt die SOS-Erweiterung (Son of Strike). Sie bietet Heap-Untersuchung, Erkennung von Heap-Beschädigung, Anzeige interner Laufzeit-Datentypen und Einblick in den Zustand laufenden verwalteten Codes, alles über SOS-Befehle.3

3.1 Unterschiede je nach Laufzeit

Welche Laufzeit Sie laden müssen und woher SOS stammt, hängt davon ab, ob die Zielanwendung .NET Framework oder .NET (Core) / .NET 5+ ist.

Ziel Laufzeitmodul Ladebefehl
.NET Framework clr.dll .loadby sos clr
.NET Core / .NET 5+ coreclr.dll .loadby sos coreclr

.loadby ist ein Befehl, der im selben Verzeichnis wie ein angegebenes Modul (clr oder coreclr) nach der Erweiterungs-DLL (sos.dll) sucht und sie von dort lädt. Der Vorteil ist, dass er zuverlässig die zur Umgebung passende SOS-Version aufgreift, in der der Dump erfasst wurde, ohne dass Sie einen vollständigen Pfad eintippen müssen.6

In WinDbg/cdb-Version 10.0.18317.1001 und höher lädt der Debugger, wenn er erkennt, dass der Zielprozess coreclr.dll (oder unter Linux/macOS libcoreclr.so) geladen hat, automatisch die .NET-Erweiterung aus der Microsoft Extension Gallery.6 Der obige Befehl .loadby ist für Fälle gedacht, in denen das automatische Laden nicht anspringt, oder wenn Sie eine ältere Version des Debuggers verwenden.

3.2 Wenn SOS nicht gefunden werden kann

In Umgebungen, in denen automatisches Laden nicht funktioniert, können Sie es mit dem Tool dotnet-sos lokal installieren.

dotnet tool install --global dotnet-sos
dotnet-sos install

Nach der Installation können Sie es innerhalb von WinDbg auch wie folgt manuell laden (das kann bei älteren Debuggern nötig sein).7

.load %USERPROFILE%\.dotnet\sos\sos.dll

3.3 Bestätigen, dass es geladen wurde

!sos.help

Alternativ versuchen Sie !Threads für Ziele der Core-Familie oder !sosstatus für Ziele der Framework-Familie – schlägt es nicht mit einem Fehler fehl und liefert einige Informationen zurück, war das Laden erfolgreich. Schlägt ein Befehl hier mit einem Fehler wie Unable to find module fehl, liegt die Ursache fast immer an einem Symbolpfad- oder Laufzeit-Mismatch (z. B. einer abweichenden Bitbreite oder Version zwischen der Umgebung, in der der Dump erfasst wurde, und der lokalen Laufzeit). Es ist in der Praxis nicht ungewöhnlich, genau hier steckenzubleiben, noch bevor man überhaupt zu den Befehlen im nächsten Kapitel kommt.

4. Ausnahmen und Stapel lesen — !clrstack und !pe

Das ist der erste Zug bei einem Dump, der bei einer unbehandelten Ausnahme abgestürzt ist.

!threads

Verwenden Sie zunächst !Threads (in lldb-Umgebungen als clrthreads bezeichnet), um verwaltete Threads aufzulisten und die Spalte Exception für jeden zu prüfen.8 Hat ein Thread eine Ausnahme, wechseln Sie zu diesem Thread.

~5s
!clrstack

!CLRStack zeigt eine Stapelverfolgung nur des verwalteten Codes an.9 Möchten Sie auch Argumente und Variablen sehen, fügen Sie -a hinzu (eine Abkürzung, die -l und -p kombiniert).

!clrstack -a
  • Erscheinen Methoden Ihres eigenen Codes, können Sie direkt ablesen, wo und über welchen Aufrufpfad es abgestürzt ist. Dass Quelldateinamen und Zeilennummern erscheinen, hängt davon ab, dass Symbole korrekt geladen sind (Kapitel 2). CLRStack zählt verwaltete Frames direkt aus den CLR-Metadaten auf, sodass das Vorhandensein von Symbolen keinen Einfluss darauf hat, ob Frames angezeigt werden. Fehlen Symbole, geht nur der Quelldateiname und die Zeilennummer verloren – Frames selbst werden nie ausgelassen.9
  • Erscheint überhaupt kein Frame Ihres eigenen Codes, vermuten Sie etwas anderes als fehlende Symbole. Mögliche Ursachen sind: Sie haben einen anderen Thread ausgewählt, der die Ausnahme nicht hat (ein Fehler bei der Thread-Auswahl), der Absturz geschah rein auf nativer Seite, sodass verwaltete Frames schlicht nicht existieren, oder der Dump-Typ (z. B. Mini) enthält zu diesem Zeitpunkt nicht genügend Stapelinformationen.

Betrachten Sie als Nächstes das Ausnahmeobjekt selbst.

!pe

!PrintException (abgekürzt !pe) zeigt die zuletzt auf dem aktuellen Thread geworfene Ausnahme an, wenn keine Adresse angegeben ist. Sie erhalten den Typnamen, die Nachricht, innere Ausnahmen (angezeigt mit -nested) und sogar die Stapelverfolgungs-Zeichenkette.10 Bei Ausnahmen wie System.NullReferenceException, bei denen der Typname allein nichts aussagt, müssen Sie es mit den über !clrstack -a sichtbaren lokalen Variablenwerten abgleichen.

5. Den Heap und Lecks verfolgen — !dumpheap -stat und !gcroot

Diese Befehle stehen im Zentrum von Untersuchungen der Art „der Speicher wächst langsam und es stürzt Stunden oder Tage später ab“. Die Vorarbeit, GC-Rückstand von einem echten Leck zu unterscheiden, wurde ausführlich in „GC-Rückstand von einem Speicherleck in .NET unterscheiden“ behandelt. Dieser Artikel setzt als Fortsetzung dessen an, indem er in den Teil geht, in dem Sie einen einzelnen Dump lesen und ergründen, was tatsächlich Speicher festhält.

!dumpheap -stat

Die Option -stat zeigt nur eine statistische Zusammenfassung des verwalteten Heaps an. Typen werden ungefähr in absteigender Reihenfolge nach Anzahl und Gesamtgröße angezeigt, sodass Sie zunächst „den Typ, der schierem Volumen nach dominiert“ identifizieren können.11 Es gibt zwei in der Praxis häufig gesehene Muster:

  • Eine Domänenklasse selbst wächst (z. B. Hunderttausende MyApp.Models.Customer-Instanzen) – irgendwo hält eine starke Referenz sie am Leben
  • Nur System.String oder Arrays sind auffällig zahlreich – das ist oft das Ergebnis interner Daten, die zu einer Domänenklasse oben in der Liste gehören; es ist meist schneller, zuerst die Domänenklasse zu vermuten, statt sofort einzelne Instanzen zu untersuchen

Sobald Sie das Ziel eingegrenzt haben, greifen Sie die Adressen einzelner Instanzen ab.

!dumpheap -type MyApp.Models.Customer

Untersuchen Sie dann, warum dieses Objekt nicht vom GC eingesammelt wurde.

!gcroot 000001a2b3c4d5e0

!GCRoot durchsucht den gesamten verwalteten Heap und die Handle-Tabelle und zählt die Wurzeln (Stapelvariablen, statische Felder, GC-Handles usw.) auf, die das angegebene Objekt erreichen.12 Zeigt die Ausgabe ein statisches Feld, das zum Zwischenspeichern verwendet wird, oder ein Ereignishandler-Abonnement, ist das ein Hauptverdächtiger für ein fehlendes Abbestellen. Der folgende Code der Art „in einem Cache belassen, ohne Freigabemöglichkeit“ ist ein klassisches Beispiel:

public static class CustomerCache
{
    // Ein statisches Dictionary ohne Entfernungspfad - es wächst nur
    private static readonly Dictionary<int, Customer> _cache = new();

    public static void Add(Customer c) => _cache[c.Id] = c;
}

Erscheint ein statischer Container wie CustomerCache in der !gcroot-Ausgabe, ist das Material dafür, auf der Code-Seite eine Ablaufrichtlinie, eine Größenobergrenze oder den Wechsel zu einer WeakReference in Erwägung zu ziehen.11

6. Automatisierte Analyse nativer Abstürze — !analyze -v

Bei nativen Abstürzen (Zugriffsverletzungen usw.) mit C++-DLLs, COM oder Anbieter-SDKs ist das der Befehl, mit dem man beginnt.

!analyze -v

!analyze ist ein Erweiterungsbefehl, der automatisierte Absturz-/Ausnahmeanalyse durchführt, und -v liefert ausführliche Ausgabe.13 Es gibt drei Felder, die besonderer Aufmerksamkeit wert sind:

  • EXCEPTION_CODE / BUGCHECK_STR: welche Art von Fehler aufgetreten ist (Zugriffsverletzung, Stapelüberlauf usw.)
  • FAULTING_IP / FOLLOWUP_IP: die Adresse der Anweisung, an der es tatsächlich abgestürzt ist, und der zugehörige Modul-/Funktionsname
  • MODULE_NAME / IMAGE_NAME: ob der Absturzort Ihr eigenes Modul oder eine DLL eines Drittanbieters ist

Liegt der Absturz innerhalb einer Anbieter-DLL statt Ihres eigenen Moduls, benötigen Sie zum weiteren Zurückverfolgen das PDB des Anbieters (das meist nicht zu erhalten ist). In der Praxis ist der realistische Landepunkt, bis zum Aufrufer zurückzuverfolgen (die zuletzt von Ihrem eigenen Code übergebenen Argumente) und zu prüfen, ob diese Werte plausibel waren. Prüfen Sie das Feld STACK_TEXT von !analyze -v, um zu sehen, was Ihr Code unmittelbar vor dem Absturz aufgerufen hat.

!analyze lässt sich auch auf andere Dumps als Ausnahme-Dumps anwenden. Vermuten Sie ein Hängenbleiben, wählen Sie den betreffenden Thread aus und führen Sie Folgendes aus, das Blockierbeziehungen zwischen Threads analysiert.

!analyze -hang

7. Eine Option, die WinDbg überspringt — dotnet-dump analyze

Müssen Sie nur verwalteten Code auf .NET Core / .NET 5+ untersuchen (ohne native DLLs oder COM), ist dotnet-dump ebenfalls eine Option – eine, die leichter ist als WinDbg.

dotnet tool install --global dotnet-dump
dotnet-dump analyze C:\CrashDumps\MyApp\MyApp_20260702_101500.dmp

Der Unterbefehl analyze öffnet eine interaktive Sitzung mit vorinstalliertem SOS und lässt Sie die meisten der bisher vorgestellten Befehle – clrstack, dumpheap, gcroot und andere – direkt verwenden, ohne das Präfix !.4

Hier ein grober Leitfaden zur Wahl zwischen beiden:

Aspekt WinDbg + SOS dotnet-dump analyze
Native Stack-Frames Sichtbar Nicht sichtbar (nur verwaltet)4
Automatisierte native Analyse über !analyze -v Verfügbar Nicht verfügbar
Linux-Dumps Können mit WinDbg unter Windows analysiert werden (x64-Build für x64-Dumps, x64-Build für Arm64-Dumps, x86-Build für x86-Dumps) Unterstützt (das Tool passend zur Bitbreite derselben Plattform verwenden)14
macOS-Dumps Nicht unterstützt (WinDbgs Linux-Dump-Unterstützung schließt macOS nicht ein) Unterstützt (.NET 5 und höher)4
Einfachheit der Einrichtung Installer oder winget Ein dotnet-Global-Tool-Befehl
Integration in plattformübergreifendes CI Erfordert etwas Aufwand Einfacher

Die praktische Trennlinie in der Produktion: Verwenden Sie WinDbg, wenn „COM, P/Invoke oder native DLLs beteiligt sein könnten“, und verwenden Sie dotnet-dump analyze, wenn es sich um „eine reine Untersuchung eines Speicherlecks in verwaltetem Code handelt, die auch in CI oder auf mehreren Plattformen laufen muss“. Da beide denselben SOS-Befehlssatz teilen, überträgt sich, was Sie bei dem einen lernen, fast direkt auf das andere. Beachten Sie, dass WinDbg für einen auf macOS erfassten Dump nicht einmal eine Option ist, sodass dotnet-dump (oder LLDB) Ihre einzige Wahl ist.

8. Ohne lesbare Symbole kommt nichts vom Fleck

Einige der obigen Verfahren funktionieren einigermaßen gut, selbst wenn Symbole (PDBs) nicht korrekt geladen sind. Wie in Kapitel 4 erwähnt, lesen !clrstack, !dumpheap -stat und !gcroot CLR-Metadaten und Heap-Daten direkt, sodass Frames und Typinformationen selbst auch ohne PDB angezeigt werden. Was bei fehlendem PDB verloren geht, sind Quelldateinamen und Zeilennummern für verwalteten Code sowie Symbolnamen für native Frames und native Module (stattdessen erscheinen Adressen statt Funktionsnamen). In Situationen, in denen Sie nur den Dump und die ausführbare Datei haben und zunächst nur verstehen möchten, was passiert ist, ist es völlig in Ordnung, mit !threads!clrstack zu beginnen, bevor Sie sich mit der PDB-Suche aufhalten. Möchten Sie jedoch bis zur Quellzeile zurückverfolgen, um die Ursache festzunageln, ist das eine andere Sache. In Kapitel 2 haben wir den Pfad zu Ihren eigenen PDBs über .sympath+ hinzugefügt, aber in der Praxis lässt allein „nicht zu wissen, wo das zu einer verteilten EXE/DLL passende PDB liegt“ Untersuchungen häufiger ins Stocken geraten, bevor sie eine Quellzeile erreichen, als die Diskussion im Sammel-Artikel vielleicht vermuten lässt.

Was ein PDB tatsächlich enthält, Portable PDBs, und Source Link (ein Mechanismus, der Quellcodeverwaltungs-Metadaten in eine Assembly einbettet, sodass ein Debugger den exakten Quellcode zum Commit abrufen kann, aus dem der Build stammt) werden alle an einem Ort in „Was ist eine PDB?“ behandelt.15 Wenn Sie Dump-Analyse in laufenden Betrieb einbauen, ist es eine PDB für jeden Build aufzubewahren und Source Link zu aktivieren eine ebenso wichtige Vorbereitung wie die Einrichtung der Dump-Sammlung selbst. Überspringen Sie das, zeigt die !clrstack-Ausgabe nie eine Quellzeile, und Sie tasten sich nur mit Adressen und Typnamen voran.

9. Eine Fallstudie — Dump-Analyse in einer Handle-Leck-Untersuchung

Ein früherer Artikel, „Untersuchung eines Langzeitbetrieb-Absturzes einer Industriekamera — der Fall des Handle-Lecks“, behandelte eine Untersuchung einer Industriekamera-Steuerungsanwendung, die nach langen Betriebsstunden abrupt abstürzte, wobei sich als Übeltäter ein Handle-Leck statt eines Speicherlecks herausstellte. Dumps erweisen sich in dieser Art von Untersuchung als wirksam, wenn folgende Kombination zutrifft:

  1. Verwenden Sie !dumpheap -stat, um zu bestätigen, dass die verwaltete Heap-Seite gesund ist (Anzahlen und Größen pro Typ wachsen nicht unbegrenzt)
  2. Wächst die Handle-Anzahl des Prozesses dennoch weiter, können Sie schließen, dass das Leck nicht verwaltete Objekte betrifft, sondern OS-Handles (Dateien, Ereignisse, von einem Kamera-SDK intern zugewiesene Handles usw.)
  3. Ist ein verwaltetes Wrapper-Objekt, das einen SafeHandle hält, noch am Leben, verfolgen Sie dessen GC-Wurzel mit !gcroot, um die Stelle zu identifizieren, an der eine Referenz gehalten wird, die eigentlich freigegeben werden sollte

Anders gesagt fungiert !dumpheap -stat als der Verzweigungspunkt zur Beurteilung, ob es sich um ein Problem mit wachsendem verwaltetem Heap handelt, und sobald feststeht, dass dem nicht so ist, verschiebt sich der Fokus der Untersuchung auf ein Werkzeug zur Anomalieerkennung an nativer Grenze wie Application Verifier. Wie man diese Art von Fundament für Anomalietests aufbaut, wird in „Ein Fundament für Windows-Anomalietests mit Application Verifier bauen“ behandelt. Dump-Analyse befasst sich mit „dem Zustand, in dem sich die Dinge gerade befinden“, während Application Verifier sich mit „einer Anomalie im Voraus reproduzieren“ befasst – beide zusammen zu verwenden ist übliche Praxis bei der Fehlerbehebung für Langzeitbetrieb-Ausfälle.

10. Zusammenfassung

Das Lesen eines Absturz-Dumps dauert länger zu meistern als das Sammeln eines solchen, aber es gibt nicht so viele unterschiedliche Muster.

  1. WinDbg installieren und den Symbolpfad sowohl auf Microsofts öffentlichen Symbolserver als auch auf Ihre eigenen PDBs richten (Kapitel 2)
  2. Die SOS-Erweiterung für .NET-Anwendungen laden (.loadby sos clr / .loadby sos coreclr, oder sich auf automatisches Laden verlassen. Kapitel 3)
  3. Beginnen Sie mit !clrstack!pe bei einer Ausnahme, !dumpheap -stat!gcroot bei wachsendem Speicher, und !analyze -v bei einem nativen Absturz (Kapitel 4–6)
  4. Ist Ihre Aufgabe eine rein verwaltete Untersuchung, ziehen Sie das leichtere dotnet-dump analyze in Betracht (Kapitel 7)

Und all dem zugrunde liegt die Verwaltung von PDB und Symbolen. Zur gleichen Zeit, zu der Sie die Dump-Sammlung einrichten, zu entscheiden, für jeden Build eine PDB aufzubewahren und Source Link zu aktivieren, macht einen gewaltigen Unterschied dafür, wie lange eine Untersuchung dauert, sobald tatsächlich ein Vorfall eintritt. Ist eine hausinterne Analyse schwierig oder fehlt Ihnen die Zeit, senden Sie uns gerne die Dumps und Protokolle, und wir analysieren sie für Sie.

Verwandte Artikel

Verwandte Beratungsleistungen

Die Komura Soft LLC übernimmt Ursachenermittlungen bei Fehlern, die Absturz-Dumps und Protokolle kombinieren, das Eingrenzen von Ausfällen, die nur nach Langzeitbetrieb auftreten, sowie Designberatung für den Aufbewahrungs- und Analyseprozess von Dumps/PDBs selbst.

  1. Microsoft Learn, Install the Windows debugger. Zur Installation von WinDbg über winget oder den Microsoft Store, zu unterstützten Betriebssystemversionen (Windows 10 1607 und höher, Windows 11) und Architekturen (x64, ARM64) sowie zum Verhalten automatischer Updates.  2 3

  2. Microsoft Learn, Symbol path for Windows debuggers. Zur Konfiguration des Symbolpfads über die Umgebungsvariable _NT_SYMBOL_PATH sowie zum Setzen eines Standardpfads zum öffentlichen Symbolserver mit dem Befehl .symfix 2

  3. Microsoft Learn, SOS debugging extension. Dazu, wie die SOS-Erweiterung verwendet werden kann, um Informationen zum verwalteten Heap zu sammeln, Heap-Beschädigung zu erkennen und interne Laufzeit-Datentypen anzuzeigen, sowie dazu, dass die Syntax in WinDbg ![Befehl] lautet.  2

  4. Microsoft Learn, Dump collection and analysis utility (dotnet-dump). Dazu, dass dotnet-dump analyze eine interaktive Sitzung bietet, in der SOS-Befehle direkt funktionieren, dass es keine nativen Stack-Frames anzeigen kann, da es kein nativer Debugger ist, sowie dazu, dass macOS-Unterstützung .NET 5 oder höher erfordert.  2 3 4

  5. Microsoft Learn, Microsoft public symbol server. Zur Symbolpfad-Syntax srv*DownstreamStore*https://msdl.microsoft.com/download/symbols sowie zur Konfiguration mit einem lokalen Cache über .symfix

  6. Microsoft Learn, Debugging Managed Code Using the Windows Debugger. Dazu, dass die .NET-Framework-Laufzeit clr.dll und die .NET-Core/.NET-5+-Laufzeit coreclr.dll ist, zum Laden von Erweiterungen aus einem nahegelegenen Verzeichnis über .loadby sowie zum automatischen Laden in WinDbg 10.0.18317.1001 und höher.  2

  7. Microsoft Learn, SOS installer (dotnet-sos). Zur lokalen Installation der SOS-Erweiterung über dotnet-sos install sowie zum bei älteren Debugger-Versionen nötigen manuellen Ladebefehl. 

  8. Microsoft Learn, SOS debugging extension - Commands. Dazu, dass der Befehl Threads (in lldb-Umgebungen als clrthreads bezeichnet) die ID, Domäne, zuletzt geworfene Ausnahme und mehr jedes Threads auflistet. 

  9. Microsoft Learn, SOS debugging extension - Commands. Dazu, dass der Befehl CLRStack eine Stapelverfolgung nur des verwalteten Codes anzeigt, dass die Option -a sowohl lokale Variablen als auch Argumente anzeigt, sowie dazu, dass Symbole (SYMOPT_LOAD_LINES) sich nur darauf auswirken, ob Quelldateinamen/Zeilennummern angezeigt werden, nicht darauf, ob Frames selbst angezeigt werden.  2

  10. Microsoft Learn, SOS debugging extension - Commands. Dazu, dass der Befehl PrintException (pe) die zuletzt auf dem aktuellen Thread geworfene Ausnahme anzeigt, wenn keine Adresse angegeben wird, und dass -nested auch verschachtelte Ausnahmen anzeigt. 

  11. Microsoft Learn, Debug a memory leak in .NET und Dump collection and analysis utility (dotnet-dump) - Analyze memory leaks and allocations. Zur Anzeige der Statistik von dumpheap -stat mit Anzahl/Gesamtgröße pro Typ sowie dazu, wie man von dort aus mit einer Untersuchung fortfährt.  2

  12. Microsoft Learn, SOS debugging extension - Commands. Dazu, dass der Befehl GCRoot den gesamten verwalteten Heap und die Handle-Tabelle durchsucht und Referenzen (Wurzeln) auf das angegebene Objekt aufzählt. 

  13. Microsoft Learn, Using the !analyze Extension und !analyze (WinDbg). Zur automatisierten Absturz-/Ausnahmeanalyse über !analyze -v, zur Bedeutung von Ausgabefeldern wie FAULTING_IP und MODULE_NAME sowie zu !analyze -hang für Untersuchungen von Hängenbleiben. 

  14. Microsoft Learn, Debug Linux dumps. Dazu, dass Linux-Dumps unter Windows mit WinDbg oder dotnet-dump analysiert werden können, sowie dazu, dass man eine zur Bitbreite (x64/Arm64/x86) der Erfassungsumgebung passende Tool-Version verwenden muss. 

Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.

Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.

Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.

Häufige Fragen

Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.

Wie analysiere ich einen .NET-Absturz-Dump mit WinDbg?
Installieren Sie WinDbg mit winget install Microsoft.WinDbg oder aus dem Microsoft Store, öffnen Sie den Dump mit windbg -z, und laden Sie die SOS-Erweiterung (.loadby sos clr für .NET Framework, .loadby sos coreclr für .NET Core / .NET 5+; aktuelle WinDbg-Versionen laden sie automatisch). Folgen Sie dann einem von drei Mustern: Bei einem Absturz durch eine Ausnahme beginnen Sie mit !clrstack, dann !pe; bei wachsendem Speicherverbrauch beginnen Sie mit !dumpheap -stat, dann !gcroot; und bei einem nativen Absturz beginnen Sie mit !analyze -v.
Funktionieren SOS-Befehle wie !clrstack ohne PDB-Symbole?
Ja. Befehle wie !clrstack, !dumpheap -stat und !gcroot lesen CLR-Metadaten und Heap-Daten direkt, sodass verwaltete Frames und Typinformationen auch ohne PDB angezeigt werden. Was ohne Symbole verloren geht, sind Quelldateinamen und Zeilennummern für verwalteten Code sowie Symbolnamen für native Frames. Möchten Sie bis zur Quellzeile zurückverfolgen, richten Sie _NT_SYMBOL_PATH (oder .symfix plus .sympath+) sowohl auf Microsofts öffentlichen Symbolserver als auch auf den Speicherort Ihrer eigenen PDBs – PDBs für eigenen Code sind nicht auf Microsofts Server gehostet.
Wie finde ich ein Speicherleck in einem Absturz-Dump?
Beginnen Sie mit !dumpheap -stat, das Anzahl und Gesamtgröße pro Typ zeigt, sodass Sie den den Heap dominierenden Typ identifizieren können. Listen Sie dann Instanzadressen mit !dumpheap -type auf und führen Sie !gcroot für eine davon aus, um die Wurzeln aufzuzählen – Stapelvariablen, statische Felder, GC-Handles –, die das Objekt am Leben halten. Ein statisches Feld, das zum Zwischenspeichern verwendet wird, oder ein in der Ausgabe auftauchendes Ereignishandler-Abonnement ist ein Hauptverdächtiger für ein fehlendes Abbestellen oder einen unbegrenzten Cache. Sieht der verwaltete Heap gesund aus, während die Anzahl der Prozess-Handles weiter wächst, handelt es sich beim Leck wahrscheinlich um OS-Handles statt um verwaltete Objekte.
Wann sollte ich dotnet-dump analyze statt WinDbg verwenden?
Verwenden Sie dotnet-dump analyze, wenn die Untersuchung rein verwalteten Code auf .NET Core / .NET 5+ betrifft, ohne native DLLs oder COM. Es ist ein einziger dotnet-Global-Tool-Befehl zur Einrichtung, öffnet eine interaktive Sitzung mit vorinstalliertem SOS und unterstützt die meisten derselben Befehle (clrstack, dumpheap, gcroot) ohne das !-Präfix. Die zentrale Einschränkung ist, dass es keine nativen Stack-Frames anzeigen kann und kein Äquivalent zu !analyze -v besitzt – verwenden Sie also WinDbg, wenn COM, P/Invoke oder native DLLs beteiligt sein könnten. Für auf macOS erfasste Dumps ist WinDbg überhaupt keine Option, sodass dotnet-dump oder LLDB die einzige Wahl ist.

Autorenprofil

Profilseite des Artikelautors.

Go Komura

Geschäftsführer von KomuraSoft LLC

Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.

Zurück zum Blog