Strategien für das Aufspüren von Speicherverlusten, wenn Sie alles getan haben Wrong

StackOverflow https://stackoverflow.com/questions/600757

  •  03-07-2019
  •  | 
  •  

Frage

Mein Programm, ach, hat ein Speicherleck irgendwo, aber ich will verdammt sein, wenn ich weiß, was es ist.

Ihre Aufgabe ist es, ein Bündel von ~ 2MB-Dateien eingelesen, tut Ersatz einig Parsen und String, dann gibt sie in verschiedenen Formaten. Natürlich bedeutet dies eine Menge von Strings und damit Speicher Tracing zeigt, dass ich eine Menge Saiten haben, das ist genau das, was ich erwarten würde. Die Struktur des Programms ist eine Reihe von Klassen (jeweils in ihrem eigenen Thread, weil ich bin ein Idiot ), die auf einem Objekt wirkt, die jede Datei im Speicher darstellt. (Jedes Objekt hat eine Eingangswarteschlange, die eine Sperre auf beiden Enden verwendet. Während dies bedeutet ich diese einfache Verarbeitung parallel auszuführen, es bedeutet auch, I im Speicher mehr 2MB Objekte sitzen muß.) Jedes Struktur des Objekts wird durch ein Schemaobjekt definiert .

Meine Verarbeitungsklassen erhöhen Ereignisse, wenn sie ihre Verarbeitung getan haben und einen Verweis auf das große Objekt übergeben, die alle meine Saiten hält es die Warteschlange zur nächsten Bearbeitungsobjekt hinzuzufügen. Ersetzen der Veranstaltung mit einem Funktionsaufruf in die Warteschlange hinzufügen nicht um das Leck zu stoppen. Einer der Ausgabeformate erfordert mich ein nicht verwaltetes Objekt zu verwenden. Entsorgen der Umsetzung () auf der Klasse nicht stoppen, das Leck. Ich habe alle Verweise auf das Schema-Objekt mit einem Indexnamen ersetzt. Kein Würfel. Ich habe keine Ahnung, was es verursacht, und keine Ahnung, wo sie suchen müssen. Die Gedächtnisspur hilft nicht, weil alles was ich sehe eine Reihe von Strings werden erstellt, und ich sehe nicht, wo die Referenzen im Speicher kleben.

Wir sind ziemlich viel los an diesem Punkt aufgeben und zurückrollen, aber ich habe ein pathologisches Bedürfnis, genau zu wissen, wie ich das durcheinander. Ich weiß, Stack-Überlauf kann nicht genau meinen Code kämmen, aber welche Strategien können Sie vorschlagen, für die Verfolgung dieses Leck nach unten? Ich bin wahrscheinlich dies in meiner eigenen Zeit tun wird, so dass jeder Ansatz ist sinnvoll.

War es hilfreich?

Lösung

Eine Technik, die ich versuchen würde, ist systematisch die Menge an Code reduzieren Sie das Problem gehen, ohne sich um das Problem demonstrieren müssen. Dies wird informell als „Teile und Herrsche“ bekannt und ist eine leistungsfähige Debugging-Technik. Sobald Sie ein kleiner Beispiel, das das gleiche Problem zeigt, wird es viel einfacher für Sie, zu verstehen. Vielleicht ist das Speicherproblem an diesem Punkt klarer werden.

Andere Tipps

Es gibt nur eine Person, die Ihnen helfen können. Dieser Name einer Person ist Tess Ferrandez . (Totgeschwiegen Schweigen)

Aber im Ernst. ihrem Blog lesen (der erste Artikel ist ziemlich relevant). Zu sehen, wie sie das Zeug debuggt wird Ihnen viel tieferen Einblick in zu wissen, was mit Ihrem Problem vor sich geht.

Ich mag die CLR Profiler von Microsoft . Es bietet einige großartige Werkzeuge für die verwalteten Heap zu visualisieren und Lecks aufzuspüren.

Ich verwende den DotTrace Profiler zum Aufspüren von Speicherlecks. Es ist viel mehr deterministisch als methodischer Versuch und Irrtum und dreht sich viel schneller Ergebnisse auf.

Für alle Aktionen, die das System durchführt, nehme ich eine Momentaufnahme dann ein paar Wiederholungen der Funktion ausführen, dann einen anderen Snapshot erstellen. Vergleicht man die beiden zeigt Ihnen alle Objekte, die erstellt wurden, dazwischen aber wurden nicht befreit. Anschließend können Sie den Stack-Frame an der Stelle ihrer Entstehung sehen, und deshalb herausarbeiten, was Instanzen nicht befreit werden.

Erhalten Sie dieses: http://www.red-gate.com/ Produkte / ants_profiler / index.htm

Die Speicher- und Leistungsprofil ist genial. Die Möglichkeit, tatsächlich richtige Zahlen statt sehen macht erraten Optimierung ziemlich schnell. Ich habe es ziemlich viel bei der Arbeit verwendet, um den Speicherbedarf unserer wichtigsten app zu reduzieren.

  1. Fügen Sie den Code an den Konstruktor der unamanaged Objekt loggt sein, wenn es onstructed und sortieren eine eindeutige ID. Verwenden Sie die eindeutige ID, wenn das Objekt wieder zerstört, und Sie können auf dest sagen, welche gehen Irre.
  2. Grep der Code für jeden Ort, den Sie ein neues Objekt konstruieren; Folge dem Codepfad zu sehen, wenn Sie eine haben zerstören spricht.
  3. Fügen Sie Verkettungs Zeiger auf die konstruierten Objekte, so dass Sie eine haben Link zum Objekt konstruiert vor und nach dem aktuellen. Dann können Sie später durch sie fegen.
  4. Fügen Referenzzähler.
  5. Sie haben einen "debug malloc" zur Verfügung?

Das verwaltete Debuggen hinzufügen in SoS (Son Strike) immens poweful ist nach unten für die Verfolgung von verwalteten Speicher ‚Lecks‘, da sie sind definitions erkennbar aus den gc Wurzeln.

Es wird in WinDbg oder Visual Studio arbeiten (obwohl es in vielerlei Hinsicht leichter in WinDbg verwenden)

Es ist gar nicht so einfach in den Griff zu bekommen. Hier ist ein Tutorial

Ich würde zweite die Empfehlung Tess Fernandez Blog auch zu überprüfen.

Wie wissen Sie, für eine Tatsache, dass Sie tatsächlich ein Speicherleck haben?

Eine andere Sache: Sie schreiben, dass Ihre Verarbeitungsklassen Ereignisse verwenden. Wenn Sie einen Event-Handler registriert haben, wird es das Objekt halten, die das Ereignis am Leben besitzt - das heißt die GC kann es nicht sammeln. Stellen Sie sicher, dass Sie alle Event-Handler de-registrieren, wenn Sie Ihre Objekte wollen Müll gesammelt werden.

Seien Sie vorsichtig, wie Sie „Leck“ zu definieren. „Verwendet mehr Speicher“ oder sogar „verbraucht zu viel Speicher“ ist nicht dasselbe wie „Memory Leak“. Dies gilt insbesondere in einer Garbage Collection-Umgebung. Es kann einfach sein, dass GC nicht den zusätzlichen Speicher zu sammeln benötigt Sie es gewohnt sind sehend. Seien Sie auch vorsichtig über den Unterschied zwischen virtueller Speichernutzung und physischen Speicher zu verwenden.

Schließlich nicht alle „Speicherlecks“ durch „Gedächtnis“ mögliche Probleme verursacht. Ich wurde einmal gesagt (nicht gefragt) einen dringenden Speicherverlust zu beheben, die IIS neu zu starten, häufig verursacht wurde. In der Tat habe ich Profilierung und fand ich eine Menge von Strings durch die String-Klasse. Ich führte einen Objektpool (von einem MSDN-Artikel) für die Stringbuilders und Speicherauslastung ging im Wesentlichen.

IIS noch ebenso oft neu gestartet. Das war, weil es kein Speicherverlust war. Stattdessen gab es nicht verwalteten Code, die Thread-sicher zu sein behauptet, aber war es nicht. Mit ihm in einem Web-Dienst (mehrere Threads) es verursacht in der ganzen C Runtime Library Haufen zu schreiben. Da niemand wurde für nicht verwaltete Ausnahmen suchen, sah niemand, bis ich mit AQtime von Automated QA eine Profilierung tun passiert. Es passiert ein Ereignisfenster haben, die die Schmerzensschreie aus der C-Laufzeitbibliothek zufällig angezeigt werden soll.

Platziert Sperren rund um die Anrufe an den nicht verwalteten Code, und der „Memory Leak“ ging.

Wenn Ihr nicht verwalteten Objekt wirklich die Ursache des Lecks ist, möchten Sie vielleicht, um es AddMemoryPressure nennen, wenn es nicht verwalteten Speicher und RemoveMemoryPressure in Finalize / Dispose zuordnet / wo immer es den nicht verwalteten Speicher freigibt. Dies wird der GC einen besseren Griff auf die Situation geben, weil sie nicht erkennen, kann es eine Notwendigkeit, sonst Sammlung zu planen.

Sie haben erwähnt, dass Ihre Veranstaltungen mit. Sie entfernen die Handler von diesen Ereignissen, wenn Sie mit Ihrem Objekt getan? Ich habe festgestellt, dass ‚lose‘ Event-Handler vielen Speicherverlust zu Problemen führen, wenn Sie eine Reihe von Handler hinzufügen, ohne dass sie, wenn Sie fertig ist zu entfernen.

Das beste Speicherprofilierungswerkzeug für .Net, ist dies:

http://memprofiler.com

Auch wenn ich hier bin, ist die beste Performance Profiler für .NET ist dies:

http://www.yourkit.com/dotnet/download/index.jsp

Sie sind auch ein gutes Preis-Leistungs-Verhältnis, eine geringe Overhead und sind einfach zu bedienen. Wer ernsthaft über .Net Entwicklung sollte diese beiden eine persönliche Investition betrachten und sofort kaufen. Beide haben eine kostenlose Testversion.

ich auf einer Echtzeit-Spiel-Engine in C # geschrieben mit über 700k Zeilen Code arbeiten und haben Hunderte von Stunden mit beiden diese Tools ausgegeben. Ich habe das Sci Tech Produkt seit 2002 und YourKit verwendet! für die letzten drei Jahre. Obwohl ich versucht habe ziemlich viele von den anderen habe ich immer an diese zurückgegeben.

IMHO, sie sind beide absolut brillant.

Ähnlich wie Charlie Martin, Sie können etwas tun:

static unigned __int64 _foo_id = 0;
foo::foo()
{
    ++_foo_id;
    if (_foo_id == MAGIC_BAD_ALLOC_ID)
        DebugBreak();
    std::werr << L"foo::foo @ " << _foo_id << std::endl;
}
foo::~foo()
{
    --_foo_id;
    std::werr << L"foo::~foo @ " << _foo_id << std::endl;
}

Wenn Sie es neu erstellen können, auch nur einmal oder zweimal mit der gleichen Zuteilung id, dies können Sie sehen, was genau dann geschieht, und es (natürlich TLS / Threading als auch behandelt werden muss, wenn nötig, aber ich habe es aus Gründen der Übersichtlichkeit).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top