Verhindern von Speicherverlusten in Windows-Anwendungen

Betroffene Plattformen

Clients – Windows 7
Server – Windows Server 2008 R2

BESCHREIBUNG

Speicherverluste sind eine Klasse von Fehlern, bei denen die Anwendung nicht mehr Arbeitsspeicher freigeben kann, wenn sie nicht mehr benötigt wird. Im Laufe der Zeit wirken sich Speicherverluste sowohl auf die Leistung der jeweiligen Anwendung als auch des Betriebssystems aus. Ein großes Leck kann aufgrund übermäßiger Pagings zu inakzeptablen Reaktionszeiten führen. Schließlich treten sowohl bei der Anwendung als auch in anderen Teilen des Betriebssystems Fehler auf.

Windows gibt den gesamten Von der Anwendung zugewiesenen Arbeitsspeicher beim Beenden des Prozesses frei, sodass sich kurz ausgeführte Anwendungen nicht erheblich auf die Gesamtsystemleistung auswirken. Allerdings können Lecks in lang laufenden Prozessen wie Diensten oder sogar Explorer Plug-Ins die Systemzuverlässigkeit erheblich beeinträchtigen und den Benutzer dazu zwingen, Windows neu zu starten, um das System wieder nutzbar zu machen.

Anwendungen können Arbeitsspeicher in ihrem Namen auf mehrere Wege zuweisen. Jeder Zuordnungstyp kann zu einem Leck führen, wenn er nach der Verwendung nicht freigegeben wird. Hier sind einige Beispiele für allgemeine Zuordnungsmuster:

  • Heapspeicher über die HeapAlloc-Funktion oder deren C/C++- Laufzeitäquivalente malloc oder new
  • Direkte Zuordnungen vom Betriebssystem über die VirtualAlloc-Funktion .
  • Kernelhandles, die über Kernel32-APIs wie CreateFile, CreateEvent oder CreateThread erstellt wurden, halten Kernelspeicher im Auftrag der Anwendung bereit.
  • GDI- und USER-Handles, die über User32- und Gdi32-APIs erstellt wurden (standardmäßig verfügt jeder Prozess über ein Kontingent von 10.000 Handles).

Bewährte Methoden

Die Überwachung des Ressourcenverbrauchs Ihrer Anwendung im Laufe der Zeit ist der erste Schritt bei der Erkennung und Diagnose von Speicherverlusten. Verwenden Sie den Windows-Task-Manager, und fügen Sie die folgenden Spalten hinzu: "Commitgröße", "Handles", "Benutzerobjekte" und "GDI-Objekte". Auf diese Weise können Sie eine Baseline für Ihre Anwendung einrichten und die Ressourcennutzung im Laufe der Zeit überwachen.

Screenshot: Seite

Die folgenden Microsoft-Tools bieten ausführlichere Informationen und können helfen, Lecks für die verschiedenen Zuordnungstypen in Ihrer Anwendung zu erkennen und zu diagnostizieren:

  • Leistungsmonitor und Ressourcenmonitor sind Teil von Windows 7 und können die Ressourcennutzung im Laufe der Zeit überwachen und graphen.
  • Die neueste Version von Application Verifier kann Heap-Leaks unter Windows 7 diagnostizieren
  • UMDH, das Teil der Debugtools für Windows ist, analysiert die Heapspeicherzuordnungen für einen bestimmten Prozess und kann helfen, Lecks und andere ungewöhnliche Nutzungsmuster zu finden.
  • Xperf ist ein anspruchsvolles Leistungsanalysetool mit Unterstützung für Heapzuordnungsablaufverfolgungen.
  • CRT-Debugheap verfolgt Heapzuordnungen nach und kann beim Erstellen eigener Heapdebugfunktionen helfen

Bestimmte Codierungs- und Entwurfspraktiken können die Anzahl von Lecks in Ihrem Code begrenzen.

  • Verwenden Sie intelligente Zeiger im C++-Code sowohl für Heapzuordnungen als auch für Win32-Ressourcen wie Kernel-HANDLEs. Die C++-Standardbibliothek stellt die auto_ptr-Klasse für Heapzuordnungen bereit. Für andere Zuordnungstypen müssen Sie Ihre eigenen Klassen schreiben. Die ATL-Bibliothek bietet einen umfangreichen Satz von Klassen für die automatische Ressourcenverwaltung für Heapobjekte und Kernelhandles.
  • Verwenden Sie compilerinterne Features wie _com_ptr_t , um Ihre COM-Schnittstellenzeiger in "intelligente Zeiger" zu kapseln und die Referenzzählung zu unterstützen. Es gibt ähnliche Klassen für andere COM-Datentypen: _bstr_t und _variant_t
  • Überwachen Sie die ungewöhnliche Arbeitsspeicherauslastung Ihres .NET-Codes. Verwalteter Code ist nicht immun gegen Speicherverluste. Informationen zum Auffinden von GC-Lecks finden Sie unter "Aufspüren verwalteter Speicherlecks" .
  • Achten Sie auf Leckmuster im clientseitigen Webcode. Zirkuläre Verweise zwischen COM-Objekten und Skriptmodulen wie JScript können zu großen Lecks in Webanwendungen führen. "Understanding and Solving Internet Explorer Leak Patterns" enthält weitere Informationen zu diesen Arten von Lecks. Sie können die JavaScript-Speicherleckserkennung verwenden, um Speicherverluste in Ihrem Code zu debuggen. Während Windows Internet Explorer 8, das mit Windows 7 ausgeliefert wird, die meisten dieser Probleme entschärft, sind ältere Browser immer noch anfällig für diese Fehler.
  • Vermeiden Sie die Verwendung mehrerer Exitpfade einer Funktion. Zuordnungen, die Variablen im Funktionsbereich zugewiesen sind, sollten in einem bestimmten Block am Ende der Funktion freigegeben werden.
  • Verwenden Sie keine Ausnahmen im Code, ohne alle lokalen Variablen in Funktionen frei zu geben. Wenn Sie native Ausnahmen verwenden, geben Sie alle Ihre Zuordnungen innerhalb des __finally-Blocks frei. Wenn Sie C++-Ausnahmen verwenden, müssen alle Heap- und Handle-Zuordnungen in intelligente Zeiger eingeschlossen werden.
  • Verwerfen oder neu initialisieren Sie ein PROPVARIANT-Objekt nicht, ohne die PropVariantClear-Funktion aufzurufen

Allgemeine Zuordnungsmuster:

Microsoft-Tools:

Zusätzliche Links: