Frage

In .NETTO-Perspektive:

  • Was ist ein memory leak?
  • Wie können Sie feststellen, ob Ihre Anwendung Lecks?Was sind die Auswirkungen?
  • Wie kann man verhindern, dass ein Speicherverlust?
  • Wenn Ihre Anwendung ein memory leak, geht es dann Weg, wenn der Prozess beendet wird oder getötet wird?Oder führen Sie Speicher-Lecks in Ihrer Anwendung auf die anderen Prozesse auf dem system, auch nach der Vollendung des Prozesses?
  • Und was ist mit nicht verwaltetem code aufgerufen via COM-Interop und/oder P/Invoke?
War es hilfreich?

Lösung

Die beste Erklärung, die ich gesehen habe, ist in Kapitel 7 der freien Grundlagen der Programmierung e-book.

Im Grunde, in .NET ein Speicherverlust tritt auf, wenn die referenzierten Objekte verwurzelt sind und daher nicht Müll gesammelt.Dies geschieht aus versehen, wenn Sie halten, um Referenzen außerhalb des vorgesehenen Bereichs.

Sie werden wissen, dass Sie über Lecks, wenn Sie anfangen, OutOfMemoryExceptions oder Ihre Speichernutzung geht über das hinaus, was man erwarten würde (PerfMon hat schöne Erinnerung Leistungsindikatoren).

Verständnis .NET's Speicher-Modell ist die beste Art und Weise zu vermeiden.Insbesondere das Verständnis, wie die garbage collector arbeitet und wie Referenzen funktionieren wieder, ich Verweise hier auf Kapitel 7 des e-book.Außerdem werden Sie sich bewusst der häufigsten Fallstricke, die wohl am meißten Veranstaltungen.Wenn der Objekt - Ein ist für ein Ereignis registriert am Objekt B, dann Objekt Ein bleiben, um bis zum Objekt B verschwindet, weil B enthält einen Verweis auf Ein.Die Lösung ist die Abmeldung Ihres events, wenn Sie fertig sind.

Natürlich, ein gutes Gedächtnis Profil können Sie Ihr Objekt-Graphen und entdecken Sie die Schachteln/Referenzierung der Objekte, zu sehen, wo Referenzen sind im kommen, und was für root-Objekt zuständig ist (red gate ants Profil, JetBrains dotMemory, memprofiler wirklich eine gute Wahl, oder Sie können verwenden Sie den nur-text - WinDbg und SOS, aber würde ich dringend empfehlen, eine kommerzielle/visual Produkt, es sei denn, du bist ein echter guru).

Ich glaube nicht verwaltetem code wird unter seiner typischen memory leaks, außer dass freigegebenen Referenzen verwaltet werden, indem der garbage collector.Ich könnte falsch sein an diesem letzten Punkt.

Andere Tipps

Streng genommen, ein Speicherleck verbraucht Speicher, der nicht mehr "genutzt" durch das Programm.

"Nicht mehr verwendet" hat mehr als eine Bedeutung, könnte es bedeuten "keine Referenz", das heißt, absolut nicht wiederhergestellt, oder es könnte bedeuten, verwiesen wird, recoverable, unbenutzt, aber behält das Programm die Verweise sowieso.Nur die später gilt .Net perfekt verwaltete Objekte.Jedoch, nicht alle Klassen sind perfekt und irgendwann eine zugrunde liegende unmanaged konnte die Umsetzung der Ressourcen dauerhaft für diesen Prozess.

In allen Fällen ist die Anwendung verbraucht mehr Speicher, als unbedingt erforderlich.Die Seiten-Effekte, abhängig von der Anzahl leckte, konnte gehen, ohne zu Verlangsamung verursacht durch übermäßige Sammlung, eine Reihe von Speicher Ausnahmen und schließlich einen fatalen Fehler, gefolgt durch erzwungene Beendigung des Prozesses.

Kennen Sie eine Anwendung hat ein problem mit dem Arbeitsspeicher, wenn die überwachung zeigt, dass mehr und mehr Speicher zugewiesen wird, um Ihren Prozess nach jeder garbage-collection-Zyklus.In einem solchen Fall sind Sie entweder zu halten, zu viel in die Speicher, oder einige zugrunde liegende unmanaged Umsetzung ist undicht.

Für die meisten Lecks, die Ressourcen werden wiederhergestellt, wenn der Prozess beendet wird, jedoch einige Ressourcen sind nicht immer erholt in einigen Fällen präzise, GDI-cursor Griffe sind berüchtigt dafür, dass.Natürlich, wenn Sie haben eine Inter-Prozess-Kommunikations-Mechanismus, Speicher in dem anderen Prozess würde nicht freigegeben werden, bis dieser Vorgang setzt oder beendet wird.

Ich denke, "was ist ein memory leak" und "was sind die Auswirkungen" Fragen wurden beantwortet auch schon, aber ich wollte noch ein paar weitere Dinge, auf die anderen Fragen...

Wie zu verstehen, ob Ihre Anwendung in Leckagen

Ein interessanter Weg ist, zu öffnen perfmon und fügen Sie Spuren für # bytes in all heaps und # Gen-2-Sammlungen in jedem Fall suchen Sie einfach in Ihren Prozess.Wenn die Ausübung einer bestimmten Funktion bewirkt, dass die Gesamtanzahl der bytes zu erhöhen, und diese Erinnerung bleibt zugeteilt, nachdem die next-Gen-2-Sammlung, könnte man sagen, dass die Funktion Speicher verliert.

Wie Sie verhindern, dass

Andere gute Meinungen bekommen habe.Ich möchte nur hinzufügen, dass vielleicht die am häufigsten übersehen Ursache .NET memory leaks ist das hinzufügen von Ereignis-Handlern, um Objekte, ohne diese zu entfernen.Einen event-handler an ein Objekt ist eine form der Verweis auf dieses Objekt, so wird verhindern, dass die Sammlung noch, nachdem alle anderen Referenzen sind gegangen.Denken Sie immer daran, zu trennen event-Handler (mit dem -= syntax in C#).

Hat das Leck Weg, wenn der Prozess beendet wird, und was über COM-interop?

Wenn Ihr Prozess beendet ist, werden alle memory mapped in seinen Adressraum zurückgefordert von der OS, einschließlich COM-Objekten serviert von DLLs.Vergleichsweise selten, COM-Objekte können serviert werden separate Prozesse.In diesem Fall, wenn Ihr Prozess beendet wird, können Sie immer noch die Verantwortung für den zugewiesenen Speicher in beliebige COM-server-Prozesse, die Sie verwendet.

Ich würde definieren, Speicher-Lecks wie ein Objekt nicht der gesamte Speicher freigesetzt wird zugeordnet, nachdem es abgeschlossen wurde.Ich habe festgestellt, dass dies passieren kann, in Ihrer Anwendung, wenn Sie mithilfe der Windows-API und COM (d.h.nicht verwaltetem code, die hat einen Fehler oder ist nicht korrekt verwaltet), die im Rahmen und in Komponenten von Drittanbietern.Ich habe auch nicht treiben nach der Verwendung von bestimmten Gegenständen, wie Stifte das Problem verursachen können.

Ich persönlich habe gelitten Out-of-Memory-Ausnahmen, die verursacht werden können, sind aber nicht exklusive zu memory leaks in dot net-Anwendungen.OOM (kann auch kommen aus pinning sehen Pinning Artical).Wenn Sie sich nicht immer OOM Fehler oder benötigen, um zu bestätigen wenn es ist eine Speicher-Leck verursacht es dann der einzige Weg ist, um ein Profil Ihrer Anwendung.

Ich würde auch versuchen, stellen Sie Folgendes sicher:

a) Alles, was Idisposable implementiert entsorgt wird entweder mit einem finally-block oder die using-Anweisung dazu gehören Pinsel, Stifte etc.(einige Leute argumentieren, um alles, was zu nichts zusätzlich)

b)Alles, was, die hat eine close-Methode geschlossen wird erneut mit endlich oder die using-Anweisung (obwohl ich gefunden habe, nicht immer in der Nähe, abhängig davon, ob Sie erklärte, das Objekt außerhalb der using-Anweisung)

c)Wenn Sie sind mit nicht verwaltetem code/windows-API ist, dass diese mit behandelt werden richtig.(einige haben clean-up-Methoden zum freigeben von Ressourcen)

Hoffe, das hilft.

Wenn Sie brauchen, um zu diagnostizieren ein memory leak in .NET, überprüfen Sie diese links:

http://msdn.microsoft.com/en-us/magazine/cc163833.aspx

http://msdn.microsoft.com/en-us/magazine/cc164138.aspx

Diese Artikel beschreiben, wie erstellen Sie ein Speicherabbild von Ihrem Prozess und wie Sie zu analysieren, so dass Sie zuerst bestimmen, wenn Ihre Leck nicht verwalteten oder verwalteten, und wenn Sie es geschafft, wie Sie herausfinden, wo es herkommt.

Microsoft hat auch eine neuere Hilfsmittel zur Unterstützung der Generierung von crash-dumps zu ersetzen ADPlus, genannt DebugDiag.

http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en

Mithilfe von CLR-Profiler von Microsoft http://www.microsoft.com/downloads/details.aspx?familyid=86ce6052-d7f4-4aeb-9b7a-94635beebdda&displaylang=en ist eine großartige Möglichkeit, um zu bestimmen, welche Objekte holding Speicher, was die Ausführung flow führt zu der Schaffung dieser Objekte, und auch die überwachung, welche Objekte dort Leben, wo auf dem heap (Fragmentierung, LOH, etc.).

Die beste Erklärung, wie die garbage collector arbeitet, ist in Jeff Richters CLR via C# Buch, (Ch.20).Lesen dieser liefert eine tolle Basis für das Verständnis, wie die Objekte bestehen.

Eine der häufigsten Ursachen der verwurzelung Objekte versehentlich durch Einhaken bis die Ereignisse auch draußen eine Klasse.Wenn Sie hook up ein externes Ereignis

z.B.

SomeExternalClass.Changed += new EventHandler(HandleIt);

und vergessen Sie zu lösen, wenn Sie nicht zu entsorgen, dann SomeExternalClass hat einen ref zu Ihrer Klasse.

Wie oben erwähnt, die SciTech memory profiler ausgezeichnete zeigen Ihnen Wurzeln der Objekte, die Sie vermuten, sind undicht.

Aber es gibt auch eine sehr schnelle Möglichkeit zu überprüfen, eine bestimmte Art ist, verwenden Sie einfach WnDBG (Sie können auch mit dieser in der VS.NET Direktfenster befestigt):

.loadby sos mscorwks
!dumpheap -stat -type <TypeName>

Tun Sie jetzt etwas, das Sie denken, wird über die Objekte dieses type (z.B.Fenster schließen).Es ist praktisch, hier eine debug-Taste, irgendwo laufen System.GC.Collect() ein paar mal.

Führen Sie dann !dumpheap -stat -type <TypeName> wieder.Wenn die Nummer nicht nach unten gehen, oder gehen nicht so viel, wie Sie es erwarten, dann haben Sie eine Grundlage für die weitere Untersuchung.(Ich habe diesen Tipp von einem seminar gegeben durch Ingo Rammer).

Ich denke, in einer verwalteten Umgebung, ein Leck wäre Sie halten einen unnötigen Verweis auf ein großes Stück der Speicher um.

Warum denken Menschen, dass ein memory leak in .NET ist nicht das gleiche wie jede andere Leck?

Ein Speicherverlust ist, wenn Sie eine Verbindung zu einer Ressource und tun nicht lassen Sie es gehen.Sie können dies tun, sowohl in verwalteten und nicht verwalteten Codierung.

Bzgl .NET, und andere Programmier-tools, es wurden Ideen zu Müll zu sammeln und andere Wege der Minimierung von Situationen, mit denen Ihre Anwendung Leck.Aber die beste Methode zur Verhinderung von Speicherlecks ist, dass müssen Sie verstehen, die zugrunde liegenden Speicher-Modell und wie es funktioniert, auf die Plattform, die Sie verwenden.

Glauben Sie, dass GC und andere Magische bereinigen Sie Ihr Chaos ist der kurze Weg, um Speicherlecks und schwierig sein wird, später zu finden.

Bei der Kodierung von nicht verwalteten, die Sie normalerweise machen sicher zu reinigen up, Sie wissen, dass die Ressourcen, die Sie aufnehmen, werden Ihre Verantwortung zu reinigen, nicht der Hausmeister ist.

In .NET, auf der anderen Seite, eine Menge Leute denken, dass der GC räumt alles.Nun, es hat einige für Sie, aber Sie müssen sicherstellen, dass es so ist..NET nicht wickeln viele Dinge, so dass Sie nicht immer wissen, ob Sie sind Umgang mit einer verwalteten oder nicht verwaltete Ressource, und Sie müssen sicherstellen, was Sie zu tun haben.Umgang mit Schriften, die GDI-Ressourcen, active directory, Datenbanken etc. ist in der Regel Dinge, die Sie brauchen, zu suchen.

In verwalteten Ausdrücken ich werde meinen Hals auf die Linie zu sagen, es geht Weg, sobald der Prozess wird getötet/entfernt.

Ich sehe viele Leute haben das aber, und ich hoffe wirklich, dass dies enden wird.Sie kann nicht den Benutzer auffordern, zu kündigen, Ihre app zu bereinigen Ihre Durcheinander!Werfen Sie einen Blick auf einen browser, dass können Sie IE, FF etc, dann öffnen Sie, sagen wir, Google Reader, lassen Sie es bleiben für einige Tage, und schauen, was passiert.

Wenn Sie öffnen Sie eine andere Registerkarte im browser, surfen Sie auf eine Seite, schließen Sie dann die Registerkarte, die Gastgeber der anderen Seite, den browser Leck, tun Sie denken, dass der browser den Speicher freizugeben?Nicht so mit dem IE.Auf meinem computer der IE einfach Essen, 1 GB memory in kürzester Zeit (etwa 3-4 Tage), wenn ich den Google Reader.Einige newspages sind noch schlimmer.

Ich denke, in einer verwalteten Umgebung ein Leck Sie wäre, zu halten eine überflüssige Referenz auf ein großes Stück der Speicher um.

Absolut.Auch nicht mit dem .Dispose () - Methode auf Einweg-Objekte bei der entsprechenden verursachen können, mem leaks.Der einfachste Weg, es zu tun, ist mit einem using-block verwenden, da es automatisch ausgeführt wird .Dispose() am Ende:

StreamReader sr;
using(sr = new StreamReader("somefile.txt"))
{
    //do some stuff
}

Und wenn Sie eine Klasse erstellen, ist die Verwendung nicht verwalteter Objekte, wenn Sie nicht implementieren IDisposable richtig, Sie könnte verursacht werden von Speicherlecks für Ihre Klasse Benutzer.

Alle Speicherlecks behoben werden, indem das Programm Kündigung.

Leck genug Speicher und kann das Betriebssystem entscheiden, das problem zu lösen für Sie.

Ich schließe mit Bernard in .net, was ein mem-Leck wäre.

Sie könnten profile Ihrer Anwendung, um zu sehen, Ihren Speicher zu verwenden, und bestimmen, dass, wenn seine Verwaltung eine Menge Speicher, wenn es nicht sein sollte, man könnte sagen, es hat ein Leck.

In verwalteten Ausdrücken ich werde meinen Hals auf der Linie zu sagen, es wird Weggehen, sobald der Prozess getötet wird/entfernt.

Nicht verwalteter code ist sein eigenes Biest und wenn ein Leck vorhanden ist, wird es Folgen ein standard-mem.Leck definition.

Beachten Sie auch, dass .NET hat zwei Haufen, einer, dem large object heap.Ich glaube, dass Objekte von etwa 85k oder größer gesetzt sind, auf diesen Haufen.Dieser Haufen hat eine andere Lebensdauer Regeln als die reguläre Haufen.

Wenn Sie sind die Schaffung großer Speicher-Strukturen (Wörterbuch oder eine Liste ist), wäre es klug, zu gehen nachschlagen, was die genauen Regeln sind.

Soweit die Rückforderung der Speicher auf Beendigung des Prozesses, es sei denn, Ihr unter Win98 oder es Mittel, alles wird wieder abgegeben, um das OS auf Kündigung.Die einzigen Ausnahmen sind Dinge, die sind geöffnet, cross-Prozess, und ein anderer Prozess hat immer noch die Ressource öffnen.

COM-Objekte kann schwierig sein, tho.Wenn Sie verwenden Sie immer die IDispose Muster, werden Sie sicher sein.Aber ich habe über ein paar interop-Assemblys, die Umsetzung IDispose.Der Schlüssel ist hier zu nennen Marshal.ReleaseCOMObject wenn Sie fertig sind mit es.Die COM-Objekte verwenden immer noch standard-COM-reference-counting.

Ich fand .Net Memory Profiler eine sehr gute Hilfe bei der Suche nach Speicherlecks in .Net.Es ist nicht kostenlos wie die Microsoft CLR Profiler, aber schneller ist und mehr auf den Punkt, meiner Meinung nach.Ein

Eine definition ist: Nicht in der Lage zu release nicht erreichbar Speicher, die nicht mehr zugeteilt werden neue Prozess während der Ausführung der Zuweisung von Prozess.Es kann zumeist geheilt werden, durch die Verwendung von GC-Techniken oder erkannt werden durch automatisierte tools.

Für mehr Informationen, besuchen Sie bitte http://all-about-java-and-weblogic-server.blogspot.in/2014/01/what-is-memory-leak-in-java.html.

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