Ich bin etwas verwirrt über die Tatsache, dass in C# nur die Referenztypen Müll gesammelt bekommen. Das bedeutet, dass GC nur die Referenztypen für die Speicherdezuweisung auswählt. Was passiert also mit den Werttypen, da sie auch Speicher im Stack belegen?Zerstören eines Strukturobjekts in C#?
Antwort
Ob sie sich auf dem Stack oder einem Teil des Heaps befinden, hängt zunächst davon ab, in welchem Kontext sie sich befinden. Wenn sie sich innerhalb eines Referenztyps befinden, befinden sie sich trotzdem auf dem Heap. (Sie sollten überlegen, wie viel Sie wirklich über die Stapel-/Heapaufteilung auf jeden Fall interessieren - wie Eric Lippert geschrieben hat, ist es largely an implementation detail.)
Grundsätzlich wird Werttyp Speicher angefordert, wenn der Kontext zurückgefordert wird - also wenn der Stapel ist Wenn Sie von einer Methode zurückkehren, die den gesamten Stack-Frame "zurückgewinnt". Wenn der Werttyp value tatsächlich Teil eines Objekts ist, wird der Speicher erneut beansprucht, wenn dieses Objekt als Garbage Collection erfasst wird.
Die kurze Antwort ist, dass Sie sich keine Sorgen machen müssen :) zu nativem Griffe, die der Stapelrahmen erhalten müsste die Freigabe, das ist ein etwas anderes Szenario.)
Ein Werttyp auf dem Stapel wird aus dem Stapel entfernt, wenn er den Gültigkeitsbereich verlässt.
Werttypen werden zerstört, sobald sie den Gültigkeitsbereich verlassen.
Werttypen freigegeben, wenn sie entfernt wird, nachdem es ich würde davon ausgehen, ausgeführt wurde
möchten auch, dass Stapel hinzuzufügen ist eine Thread-Ebene und Heap ist auf Anwendungsdomänenebene.
Also, wenn ein Thread endet, würde es den Stack-Speicher reclam, die von diesem bestimmten Thread verwendet wird.
Es sind zu viele Verben in dieser Frage verwendet, wie zerstört, zurückgewonnen, freigegeben, entfernt. Das passt nicht gut zu dem, was tatsächlich passiert. Eine lokale Variable hört einfach auf zu sein, Norwegian parrot style.
Eine Methode hat einen einzigen Einstiegspunkt, zuerst passiert, dass der CPU-Stack-Zeiger eingestellt ist. Erstellen eines "Stack Frame", Speicherplatz für die lokalen Variablen. Die CLR garantiert, dass dieser Space auf 0 initialisiert wird, nicht ein Feature, das Sie wegen der definitiven Zuweisungsregel in C# stark verwenden.
Eine Methode hat einen einzigen Exitpunkt, auch wenn der Methodencode mit mehreren return
-Anweisungen gespickt ist. An diesem Punkt wird der Stapelzeiger einfach auf seinen ursprünglichen Wert zurückgesetzt. In der Tat "vergisst" es, dass die lokalen Variablen dort waren. Ihre Werte werden nicht 'geschrubbt', die Bytes sind immer noch da. Aber sie werden nicht lange dauern, der nächste Aufruf in Ihrem Programm wird sie wieder überschreiben. Die CLR-Zero-Initialization-Regel stellt sicher, dass Sie nie diese alten Werte beobachten können, die unsicher wären.
Sehr, sehr schnell, dauert nicht mehr als einen einzigen Prozessorzyklus. Ein sichtbarer Nebeneffekt dieses Verhaltens in der C# -Sprache ist, dass Werttypen keinen Finalizer haben können. Stellen Sie sicher, dass keine zusätzlichen Arbeiten erforderlich sind.
Diese lokale Variable gibt es nicht mehr! Es hat aufgehört zu sein! Es ist eine Ex-Variable. :) –
Ich bin etwas verwirrt über die Tatsache, dass in C# nur die Referenztypen Müll gesammelt bekommen.
Dies ist keine Tatsache.Oder, die Wahrheit oder Falschheit dieser Aussage hängt davon ab, was Sie mit "Müll sammeln" meinen. Der Garbage Collector betrachtet beim Sammeln Werttypen. diese Werttypen könnten am Leben und hält sich an einem Referenztyp sein:
struct S { public string str; }
...
S s = default(S); // local variable of value type
s.str = M();
wenn der Garbage Collector läuft es sieht bei s, weil es, dass s.str ist noch am Leben zu bestimmen, benötigt.
Mein Vorschlag: klären Sie genau was Sie mit dem Verb "bekommt Müll gesammelt".
Der GC wählt nur die Referenztypen für die Speicherzuweisung aus.
Auch dies ist keine Tatsache. Angenommen, Sie eine Instanz
class C { int x; }
der Speicher für die Ganzzahl auf dem Garbage Collected Heap werden müssen, und daher durch den Speicherbereinigungs aufgearbeiteten, wenn die Instanz von C unbewurzelten wird.
Warum glauben Sie die Unwahrheit, dass nur die Erinnerung an Referenztypen vom Garbage Collector freigegeben wird? Die korrekte Aussage ist, dass der Speicher, der vom Müllsammler war freigegeben durch den Müllsammler ist, der ich denke, macht vollkommenen Sinn. Der GC hat es zugeteilt, so dass es für die Säuberung zuständig ist.
Was passiert also mit den Werttypen, da sie auch den Speicher auf dem Stack belegen?
Nichts passiert ihnen. Nichts muss ihnen passieren. Der Stapel ist eine Million Bytes. Die Größe des Stapels wird bestimmt, wenn der Thread startet; Es beginnt bei einer Million Bytes und bleibt während der gesamten Ausführung des Threads eine Million Byte. Speicher auf dem Stapel wird weder erstellt noch zerstört; nur sein Inhalt wird geändert.
"Speicher auf dem Stapel wird weder erstellt noch zerstört" - Ich schlage vor, wir nennen dies ** Lipperts Gesetz von [Stack] Memory Preservation **. :) –
Jede Werttypinstanz in .NET ist Teil von etwas anderem, das eine größere einschließende Werttypinstanz, ein Heap-Objekt oder ein Stapelrahmen sein könnte. Wann immer etwas von diesen Dingen entsteht, werden auch Strukturen in ihnen entstehen; diese Strukturen werden dann weiter existieren, solange das Ding, das sie enthält, tut. Wenn das Ding, das die Struktur enthält, aufhört zu existieren, wird auch die Struktur. Es gibt keine Möglichkeit, eine Struktur zu zerstören, ohne den Container zu zerstören, und es gibt keine Möglichkeit, etwas zu zerstören, das eine oder mehrere Strukturen enthält, ohne die darin enthaltenen Strukturen zu zerstören.
Vielen Dank für den Hinweis auf diesen umfassenden Artikel. Ich fand die globale Direktive von Eric Lippert sehr konsistent mit der gesamten C# -Philosophie: "Habe nur eine Sorge um die Semantik, wir kümmern uns um den Rest für dich" –