2009-07-15 4 views
4

Gibt es einen erweiterten Artikel, den ich lesen kann, die Speicher für verschiedene Typen (Wert und Verweis) im .net-Framework zugeordnet werden kann.Speicherzuweisung von Werttypen und Referenztypen in .net Framework

zum Beispiel wissen wir, dass Werttypen Platz auf einem Stapel zugewiesen sind, aber wie wird das verwaltet?

Wie werden Referenztypen in einem Heap verwaltet und wo sind die tatsächlichen Werte gespeichert? (Referenztyp wie jede Klasse enthält viele Werttypen, wo werden sie gespeichert und wie werden sie verwaltet)

Antwort

1

Wenn eine Methode aufgerufen wird, ist der von Werttypen benötigte Platz im Voraus bekannt (er kann von der Compiler). Dieser Speicherplatz ist auf dem Stack reserviert und nur für die Dauer des Methodenaufrufs verfügbar. Für jeden neuen Methodenaufruf wächst der Speicher, der auf dem Stapel verwendet wird, und wenn die Methode beendet wird, schrumpft er auf die vorherige Ebene zurück.

Referenztypen werden auf dem Heap zugewiesen. Der Heap ist im Grunde ein Speicherblock, der für diesen Zweck verwendet wird. Ein auf dem Heap gespeichertes Objekt sind in erster Linie die Felder des Objekts, das in dem Speicher gespeichert ist, der dem Objekt zugeordnet ist. Daher werden Werttypfelder "innerhalb" des Objekts auf dem Heap gespeichert. Referenztypfelder werden als Referenz (oder Zeiger) auf das referenzierte Objekt gespeichert. Der Speicher auf dem Heap wird durch Garbage Collection verwaltet. Es ist ein komplexes Thema, aber die Kurzgeschichte ist, dass Speicher, der unbenutzten Objekten auf dem Heap zugewiesen wurde, freigegeben wird und somit in regelmäßigen Abständen vom Garbage Collector wiederverwendet werden kann.

10

Es ist komplizierter, als Sie vielleicht denken. Selbst Ihre Behauptung, dass "Werttypen auf dem Stapel zugeordnet sind", ist nicht korrekt. Zum Beispiel:

class Foo 
{ 
    int x; 
} 

int ist ein Werttyp, aber der Wert für x wird immer auf dem Heap sein, weil es mit dem Rest der Daten für die Instanz von Foo gespeichert werden, die eine Klasse ist.

Darüber hinaus machen erfasste Variablen für anonyme Funktionen und Iteratorblöcke das Leben schwieriger.

Ich habe eine article about C# heap/stack memory Sie möglicherweise nützlich finden, aber Sie möchten vielleicht auch Eric Lipperts Blog-Post auf "The stack is an implementation detail" lesen. Insbesondere könnte ein zukünftiger C# -Compiler beschließen, alle seine lokalen Variablen auf dem Heap zu speichern, wobei der Stapel nur dazu verwendet wird, einen Verweis auf eine Instanz zu halten, die am Anfang der Methode erstellt wurde und die C# -Spezifikation nicht übertrifft alle.

3

Ein Werttyp ist "zugeordnet", wo er definiert ist.

Was das bedeutet, hängt davon ab, wo Sie sie definieren:

  • In einer Klasse/Struktur, als ein Feld in dieser Struktur, die Klasse/Struktur im Speicher vergrößern den Werttyp Wert dort zu passen
  • Als lokale Variable in einer Methode, im Stack oder als Register oder als Feld in einer generierten Klasse (bei Verwendung von "closures"), abhängig von Optimierungen
  • Als Parameter für eine Methode auf dem Stack oder als Register, abhängig von Optimierungen

Ein Referenztyp ist eine Art Doppelwert. Ein Referenztyp ist im Kern ein Zeiger, und der Zeigerwert folgt den gleichen Regeln für "Zuweisung" wie ein Werttyp, aber sobald Sie einen Wert darin speichern, d. ein Verweis auf ein Objekt, das Objekt befindet sich woanders auf dem Heap.

Mit anderen Worten, die Referenzvariable selbst ist als Werttyp "zugeordnet", aber das Objekt, auf das sie sich bezieht, befindet sich auf dem Heap.

Wenn Sie ein Objekt aus einer Klasse konstruieren, wird auf dem Heap Speicherplatz zugewiesen, um alle Felder dieser Klasse und einige Overhead in diesem Raum anzupassen.

Ich kann mich erinnern, dass Jon Skeet einen Artikel über das Thema hat, ich bin mir sicher, dass er bald mit einer Antwort einspringen wird, also bleibt dran.

+3

und da war er, während ich meine Antwort tippte. –

2

Erinnern Sie sich an die Regel, Referenztypen gehen immer zum Heap, während Werttypen immer dorthin gehen, wo sie deklariert wurden. Wenn ein Werttyp außerhalb einer Methode deklariert ist, aber innerhalb eines Referenztyps, wird er innerhalb des Referenztyps auf dem Heap platziert.