2010-02-25 8 views
5

Speicherleck ist, wenn es ungenutzten Speicher in der Anwendung gibt und GC kann es sammeln, normalerweise tritt es auf, wenn in Anwendung wir unerwünschte starke Referenz eines Objekts halten, und GC wird den Pfad finden (direkt und indirekt) Es kann dieses Objekt freigeben, aber das alles gilt für Referenztypen, die in der Heap-Speicherzuweisung meinen.Ist es möglich, dass Speicherverlust bei Stack in .NET auftritt?

Aber was ist mit Stack Und soweit ich weiß, GC wird nicht verantwortlich für die Reinigung des Stapels wird es automatisch reinigen, wenn die Funktion zurückkehrt.

Also meine Frage ist, gibt es eine Chance, dass Speicherverlust im Stapel auch auftritt ?, wenn ja dann bei welchem ​​Szenario und was sind die besten Praktiken, um diese Art von Leck zu vermeiden.

Antwort

2

Wenn Sie rekursive Funktionen schreiben, die stapellokale Verweise auf große Daten behalten, die bei subrekursiven Aufrufen nicht benötigt werden, handelt es sich um eine Art von Speicherleck. Es ist jedoch sehr ungewöhnlich, dass dies ein Problem darstellt trainieren.

Allgemeiner gesagt, wenn Sie etwas haben, wie

Main() { 
    var s = ReadInAGiganticString(); // say 10 Megs long 
    Server(s.Substring(0,5));   // but I only care about first 5 chars 
} 
Server(s) { 
    while(true) { ... }    // but 10M is on stack forever 
} 

dann ist dies eine Art von Stack-Raum-Leck, aber auch hier ist es in der Praxis unwahrscheinlich. Die Lösung ist einfach:

Main() { 
    var s = ReadInAGiganticString(); 
    var t = s.Substring(0,5); 
    s = null;       // the fix 
    Server(t); 
} 
Server(s) { 
    while(true) { ... } 
} 

Im Allgemeinen, wenn Sie jemals eine Riesen Variable auf dem Stapel direkt vor einem Aufruf, die ‚eine lange Zeit‘ und die Variable dauern wird nicht mehr verwendet wird, können Sie es nullen um sicherzustellen, dass es vor dem Einstieg in den "langen" Anruf bestätigt werden kann.

(Es ist möglich, dass ein Optimierer dies basierend auf Erreichbarkeitsanalyse für Sie tun kann.)

Beachten Sie, dass die oben genannte Antwort auf Verweise auf dem Heap zugeordneten Objekte, die auf dem Stapel verwurzelt sind. Wenn Sie andererseits über stapelbelegten Speicher verfügen (z. B. eine gigantische Struktur oder ein Stackalloc-Ding), dann ist die Behebung nicht so einfach, aber das ist in der Praxis noch seltener (wer schafft jemals riesige Strukturen?).

+1

Nur der Verweis auf die Zeichenfolge befindet sich auf dem Stapel, die Zeichenfolge selbst befindet sich auf dem Heap. –

0

Variablen, die im Stapel zugeordnet sind, werden nach dem Ende des Blocks zerstört. Es ist also nicht möglich, dass ein Speicherleck entstehen kann. Bed Praxis ist, eine Variable zu erstellen, die nur in einem bestimmten Block außerhalb dieses Blocks verwendet wird

0

Wie Sie sagen, der GC reinigt nicht den Stapel. Der vom Stapel verwendete Platz wird jedoch während des Abwickelns zurückgewonnen. Wenn also der Stapel geöffnet wird, wird der Stapelzeiger "zurück" bewegt, und der Platz kann wiederverwendet werden.

Wenn der Stack-Speicherplatz nicht mehr ausreicht, wird die StackOverflowException ausgelöst. Dies liegt normalerweise an einem Programmierfehler mit unbegrenzter Rekursion.

0

Ohne zu viel über die Interna von .NET zu wissen, würde ich sagen, dass wenn Sie eine Stack-Leckage haben Sie ein Programm abstürzen, da die Funktion/Methode Absenderadresse auf dem Stapel gespeichert wird (wahrscheinlich sowieso) .

Wenn Ihr Stack irgendwie falsch ausgerichtet ist, haben Sie viel größere Probleme als ein Speicherleck.

Normalerweise werden Methodenparameter und Rückgabewerte auf dem Stack gespeichert (wenn nicht optimiert, um über CPU-Register gesendet zu werden).

0

Nein, solange Sie Sicherheitscode verwenden, können Speicherlecks für Stack-Variablen nicht auftreten.

1

Ein Speicherverlust kann auftreten, wenn Sie nicht verwaltete Ressourcen nicht ordnungsgemäß freigeben können. Daher habe ich Angst, dass wenn Sie ein verwaltetes Objekt an eine Methode senden und dieses Objekt eine nicht verwaltete Ressource umhüllt und die nicht verwaltete Ressource nicht ordnungsgemäß freigibt, wird ein Speicherverlust auftreten. Der Stapel wird die verwaltete Referenz freigeben, die nicht verwaltete Ressource bleibt jedoch aktiv.

Verwandte Themen