Frage

Ich habe den folgenden Code:

MemoryStream foo(){
    MemoryStream ms = new MemoryStream();
    // write stuff to ms
    return ms;
}

void bar(){
    MemoryStream ms2 = foo();
    // do stuff with ms2
    return;
}

Gibt es eine Chance, dass die Memorystream, die ich zugewiesen habe irgendwie später entsorgt werden scheitern?

Ich habe einen Peer-Review bekomme darauf bestanden, dass ich diese von Hand schließen, und ich kann die Information zu sagen, nicht finden, wenn er einen wichtigen Punkt hat oder nicht.

War es hilfreich?

Lösung

Wenn etwas Einweg ist, sollten Sie immer es entsorgen. Sie sollten eine using-Anweisung in Ihrer Bar () -Methode verwenden, um sicherzustellen, ms2 Angeordnet wird.

Es wird schließlich vom Garbage Collector aufgeräumt, aber es ist immer gut, die Praxis zu entsorgen. Wenn Sie FxCop auf Ihrem Code ausführen, würde es Flag es als Warnung.

Andere Tipps

Sie werden nichts auslaufen - zumindest in der aktuellen Implementierung

.

Entsorgen Aufruf wird nicht auf den Speicher von Memory verwendet aufzuräumen schneller. Es wird Stream stoppen für unprofitabel Read / Write Anrufe nach dem Aufruf, die nicht für Sie nützlich sein können.

Wenn Sie absolut sicher sind, dass Sie nie wollen von einem Memorystream auf eine andere Art von Strom bewegen, es wird nicht Sie schaden nicht nennen entsorgen zu tun. Allerdings ist es im Allgemeinen gute Praxis zum Teil, weil, wenn Sie jemals tun Wechsel einen anderen Strom zu verwenden, Sie möchten nicht durch ein gebissen werden schwer zu finden Fehler, weil Sie den einfachen Weg gewählt haben früh auf. (Auf der anderen Seite gibt es das Argument YAGNI ...)

Der andere Grund, es trotzdem zu tun, ist, dass eine neue Implementierung können Ressourcen einzuführen, die auf Entsorgen frei werden würde.

Ja, es ist a Leck , je nachdem, wie Sie LEAK definieren und wie viel SPÄTER meinen Sie ...

Wenn durch Leck meinen Sie „der Speicher zugewiesen bleibt, für den Einsatz nicht zur Verfügung, auch wenn Sie verwenden es getan“ und durch letztere meinen Sie jederzeit nach entsorgen anrufen, dann ja dann kann es ein Leck sein, obwohl seine nicht dauerhaft (dh für die Lebensdauer Ihrer Anwendungen Laufzeit).

den verwalteten Speicher durch die Memorystream verwendet zu befreien, Sie müssen es Nichtbezug , indem Sie Ihre Referenz darauf zunichte gemacht, so dass er sofort für die Garbage Collection in Anspruch genommen werden. Wenn Sie dies nicht tun, dann erstellen Sie eine temporäre Leck aus der Zeit, bist du es getan verwenden, bis Ihre Referenz den Gültigkeitsbereich verlässt, weil in der Zwischenzeit nicht der Speicher für die Zuordnung zur Verfügung.

Der Vorteil der Verwendung von Anweisung (über einfach Aufruf entsorgen) ist, dass Sie Ihre Referenz in der Anweisung using ERKLäREN können. Wenn die Anweisung using beendet ist, wird nicht nur Deponieren Sie genannt, aber Ihre Referenz geht out of scope, effektiv die Referenz zunichte gemacht und machen Ihre Aufgabe, die für die Garbage Collection sofort, ohne dass Sie daran denken, die „reference = null“ Code zu schreiben.

Während Unterlassungen zu Recht entfernt Nichtbezug kein klassisches „permanent“ Speicherleck, es hat auf jeden Fall die gleiche Wirkung. Zum Beispiel, wenn Sie Ihre Referenz halten auf den Memorystream (auch nach dem Aufruf entsorgen), und ein wenig weiter unten in Ihrer Methode versuchen Sie mehr Speicher zuzuweisen ... bei dem verwendeten Speicher von Ihrem noch referenzierten Speicherstrom nicht zur Verfügung Ihnen bis zunichte machen Sie die Referenz oder den Gültigkeitsbereich verlässt, auch wenn Sie es genannt dispose und verwenden getan.

Dies ist bereits beantwortet, aber ich werde nur hinzufügen, dass das althergebrachten Prinzip der Information Hiding bedeutet, dass Sie zu einem späteren Zeitpunkt können Refactoring wollen:

MemoryStream foo()
{    
    MemoryStream ms = new MemoryStream();    
    // write stuff to ms    
    return ms;
}

zu:

Stream foo()
{    
   ...
}

Dies unterstreicht, dass Anrufer sollten es egal, welche Art von Strom zurückgeführt wird, und ermöglicht es, die interne Implementierung (zum Beispiel, wenn für Unit-Tests spöttisch) zu ändern.

Sie müssen dann in Schwierigkeiten, wenn Sie nicht entsorgen in Ihrer Bar-Implementierung verwendet haben:

void bar()
{    
    using (Stream s = foo())
    {
        // do stuff with s
        return;
    }
}

Alle Streams implementieren IDisposable. Wickeln Sie Ihren Speicherstrom in einer using-Anweisung und Sie werden schön und gut sein. Die Verwendung von Block wird Ihren Strom gewährleistet ist, geschlossen und so angeordnet, egal was.

, wo immer Sie Foo aufrufen können Sie tun, indem (Memorystream ms = foo ()) und ich denke, Sie immer noch in Ordnung sein sollte.

Beim .Dispose() (oder Umwickeln mit Using) ist nicht erforderlich.

Der Grund, warum Sie .Dispose() nennen, ist auf lassen Sie die Ressource so schnell wie möglich .

Denken Sie

in Bezug auf die, sagen wir, der Stack-Überlauf-Server, wo wir eine begrenzte Anzahl an Speicher haben und Tausende von Anfragen auf sich warten. Wir wollen nicht warten, für geplante Müllabfuhr, wollen wir, dass der Speicher freizugeben, so schnell wie möglich so ist es für neue eingehende Anfragen.

Sie werden nicht ein Speicherleck, aber Ihr Code Rezensent ist richtig, um anzuzeigen, sollten Sie Ihren Strom schließen. Es ist höflich, dies zu tun.

Die einzige Situation, in der Sie ein Speicherleck könnte, ist, wenn Sie versehentlich einen Verweis auf den Strom verlassen und es nie schließen. Sie sind undicht noch nicht wirklich Speicher, aber Sie sind unnötig die Menge der Verlängerung, die Sie behaupten, es zu werden.

Ich würde empfehlen, den Memorystream in bar() in einer using Aussage vor allem für die Konsistenz Verpackung:

  • jetzt rechts Memory nicht freien Speicher auf .Dispose(), aber es ist möglich, dass in Zukunft irgendwann könnte es, oder Sie (oder jemand anderes in Ihrem Unternehmen) könnten es mit Ihrem eigenen Memory ersetzen, tut etc.
  • Es hilft, ein Muster in Ihrem Projekt zu etablieren, um sicherzustellen, alle Streams entsorgt bekommen - die Linie stärker mit den Worten: statt „einig Streams„alle Bäche entsorgt werden müssen“gezogen wird, müssen entsorgt werden , aber bestimmte diejenigen haben nicht“...
  • Wenn Sie jemals den Code ändern für die Rückgabe andere Arten von Streams zu ermöglichen, müssen Sie es ändern sowieso entsorgen.

Eine andere Sache, die ich in der Regel in Fällen wie foo() tun bei der Erstellung und der Rückkehr ein IDisposable, dass zwischen der Konstruktion des Objekts jeder Fehler zu gewährleisten ist und die return durch eine Ausnahme gefangen wird, verfügt das Objekt und rethrows die Ausnahme:

MemoryStream x = new MemoryStream();
try
{
    // ... other code goes here ...
    return x;
}
catch
{
    // "other code" failed, dispose the stream before throwing out the Exception
    x.Dispose();
    throw;
}

Wenn ein Objekt implementiert IDisposable, müssen Sie die .Dispose Methode aufrufen, wenn Sie fertig sind.

In einigen Objekten bedeutet Entsorgen der gleichen wie Schließen und umgekehrt, in diesem Fall entweder gut ist.

Nun, für Ihre Frage, nein, Sie werden nicht ein Speicherleck auf.

Ich bin kein .net-Experte, aber vielleicht ist das Problem hier Ressourcen, nämlich die Datei-Handle, und nicht-Speicher. Ich denke, der Sammler Müll wird schließlich den Strom befreien und den Griff in der Nähe, aber ich denke, es ist immer am besten Praxis wäre es explizit zu schließen, um sicherzustellen, dass Sie die Inhalte auf die Festplatte spülen.

Die Entsorgung von nicht verwalteten Ressourcen ist nicht deterministisch in Müll gesammelt Sprachen. Auch wenn Sie explizit Dispose aufrufen, Sie haben absolut keine Kontrolle über, wenn der Hintergrundspeicher tatsächlich freigegeben wird. Entsorgen Sie wird implizit aufgerufen, wenn ein Objekt den Gültigkeitsbereich verlässt, sei es durch Verlassen einer using-Anweisung sein, oder die Aufrufhierarchie von einer untergeordneten Methode Aufspringen. Dies alles wird gesagt, manchmal das Objekt tatsächlich ein Wrapper für eine verwaltete Ressource sein kann (beispielsweise Datei). Aus diesem Grunde ist es empfehlenswert, explizit zu schließen in finally-Anweisungen oder die Anweisung using zu verwenden. Prost

MemorySteram ist nichts anderes als Array von Byte, das Objekt verwaltet wird. Vergessen zu entsorgen oder schließen dies hat keine Nebenwirkungen anders als über den Kopf der Finalisierung.
Nur überprüfen Konstruktor oder Flush-Methode von Memorystream in Reflektor und es wird klar sein, warum Sie kümmern müssen nicht über Schließung oder andere als nur für selbst folgende gute Praxis zu entsorgen.

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