Sind Speicherverluste in verwalteten Umgebungen wie .NET möglich?

7

In C ++ ist es leicht möglich, ein permanentes Speicherleck zu haben - einfach Speicher reservieren und nicht freigeben:

%Vor%

und dieser Speicher bleibt für die Lebensdauer des Heapspeichers reserviert (normalerweise genauso lang wie die Programmlaufzeit).

Ist das Gleiche (ein Fall, der zu einem bestimmten nicht referenzierten Objekt führt, das nie freigegeben wurde, während die Speicherverwaltungsmechanismen ordnungsgemäß funktionieren) in einem C # -Programm möglich?

Ich habe diese Frage und Antworten darauf sorgfältig gelesen und es werden einige Fälle erwähnt, die zu einem höheren Speicherverbrauch führen als erwartet oder IMO eher extreme Fälle wie Deadlocking der Finalizer-Thread, aber kann ein permanentes Leck in einem C # -Programm mit normal funktionierenden Speicherverwaltung gebildet werden?

    
sharptooth 15.04.2011, 10:25
quelle

7 Antworten

24

Es hängt davon ab, wie Sie ein Speicherleck definieren. In einer nicht verwalteten Sprache denken wir in der Regel an ein Speicherleck als eine Situation, in der Speicher zugewiesen wurde und keine Referenzen darauf existieren. Daher können wir sie nicht freigeben.

Diese Art von Lecks ist in .NET kaum zu erstellen (es sei denn, Sie rufen in nicht verwalteten Code auf oder es liegt ein Fehler in der Laufzeit vor).

Sie können jedoch eine andere "schwächere" Form von Lecks erhalten: wenn ein Verweis auf den Speicher existiert (so ist es immer noch möglich, die Referenz zu finden und zurückzusetzen, so dass der GC die Speicher normalerweise), aber Sie Gedanke hat es nicht, so dass Sie angenommen das Objekt, auf das verwiesen wird, erhalten GC'ed. Dies kann leicht zu einem unbegrenzten Wachstum des Speicherverbrauchs führen, da Sie Referenzen auf Objekte häufen, die nicht mehr verwendet werden, die jedoch nicht als Garbage Collected erfasst werden können, da sie immer noch in Ihrer App referenziert werden.

Was in .NET normalerweise als Speicherleck angesehen wird, ist einfach eine Situation, in der Sie vergessen haben, dass Sie einen Verweis auf ein Objekt haben (z. B. weil Sie sich nicht von einem Ereignis abmelden konnten). Aber die Referenz existiert, und wenn Sie sich daran erinnern, können Sie es löschen und das Leck wird verschwinden.

    
jalf 15.04.2011, 10:42
quelle
2

Sie können nicht verwalteten Code in .NET schreiben, wenn Sie möchten, haben Sie Ihren Code mit unsicheren Schlüsselwort umschließen, wenn Sie also unsicheren Code schreiben, sind Sie nicht zurück auf das Problem der Speicherverwaltung selbst und wenn nicht Speicherleck?

    
Kiran Bheemarti 15.04.2011 10:38
quelle
1

Es ist nicht genau ein Speicherleck, aber wenn Sie direkt mit Hardware-Treibern kommunizieren (dh nicht über eine richtig geschriebene .net-Erweiterung einer Reihe von Treibern), dann ist es ziemlich möglich, die Hardware in einen Zustand zu versetzen, obwohl es in Ihrem Code möglicherweise ein tatsächliches Speicherleck gibt oder nicht, können Sie nicht mehr auf die Hardware zugreifen, ohne sie oder den PC neu zu starten ...

Ich bin mir nicht sicher, ob das eine nützliche Antwort auf Ihre Frage ist, aber ich fand es erwähnenswert.

    
Frosty840 15.04.2011 10:38
quelle
1

GC verzögert normalerweise die Sammlung von nicht erreichbarem Speicher zu einem späteren Zeitpunkt, wenn eine Analyse der Referenzen zeigt, dass der Speicher nicht erreichbar ist. (In einigen eingeschränkten Fällen kann der Compiler den GC unterstützen und warnen, dass eine Speicherzone nicht erreichbar ist, wenn dies der Fall ist.)

Abhängig vom GC-Algorithmus wird nicht erreichbarer Speicher erkannt, sobald ein Erfassungszyklus ausgeführt wird, oder er bleibt möglicherweise für eine bestimmte Anzahl von Erfassungszyklen unerkannt (z. B. zeigt generational GC dieses Verhalten). Einige Techniken haben sogar blinde Flecken, die nie gesammelt werden (Verwendung des Referenzzählers zum Beispiel) - einige verweigern ihnen den Namen des GC-Algorithmus, sie sind wahrscheinlich im allgemeinen Kontext ungeeignet.

Der Nachweis, dass eine bestimmte Zone zurückgewonnen wird, hängt vom Algorithmus und vom Speicherzuweisungsmuster ab. Für einen einfachen Algorithmus wie Mark und Sweep ist es einfach, eine Grenze zu bilden (sagt bis zum nächsten Sammlungszyklus), für komplexere Algorithmen ist die Angelegenheit komplexer (unter einem Schema, das eine dynamische Anzahl von Generationen verwendet, die Bedingungen, unter denen a vollständige Sammlung ist nicht sinnvoll für jemanden, der nicht vertraut mit dem Detail des Algorithmus und der genauen Heuristik verwendet)

    
AProgrammer 15.04.2011 12:16
quelle
0

Eine einfache Antwort ist, dass klassische Speicherlecks in GC-Umgebungen unmöglich sind, da klassischerweise ein Speicherleck durchleuchtet ist, da es als nicht referenzierter Block keine Möglichkeit für die Software gibt, ihn zu finden, um ihn zu bereinigen.

Andererseits ist ein Speicherverlust eine Situation, in der die Speichernutzung eines Programms unbegrenztes Wachstum aufweist. Diese Definition ist nützlich, wenn Sie analysieren möchten, wie die Software bei der Ausführung als Dienst ausfallen könnte (wenn Dienste voraussichtlich für mehrere Monate ausgeführt werden).

Daher kann jede erweiterbare Datenstruktur, die weiterhin Referenzen auf nicht benötigte Objekte enthält, dazu führen, dass die Servicesoftware aufgrund der Erschöpfung des Adressraums effektiv ausfällt.

    
Chris Becke 15.04.2011 10:37
quelle
0

Einfachstes Speicherleck:

%Vor%

Instanzen von Listener werden nie gesammelt.

    
TDaver 15.04.2011 10:37
quelle
-1

Wenn wir Speicherleck als eine Bedingung definieren, bei der ein Speicher, der zum Erstellen von Objekten verwendet werden kann, nicht verwendet werden kann oder ein Speicher, der freigegeben werden kann, dann nicht

Speicherlecks können passieren in:

  • Ereignisse in WPF, in denen schwache Ereignisse verwendet werden müssen. Dies kann insbesondere in Angehängte Eigenschaften auftreten.
  • Große Objekte

Large Object Heap Fragmentierung

Ссылка

    
Aliostad 15.04.2011 10:28
quelle