Heap, Stack, VTable (CSharp)

aggroman

Lt. Junior Grade
Registriert
Sep. 2008
Beiträge
449
Guten Tag,

ich beschäftige mich gerade mit der Speicherverwaltung und OOP.

Mal angenommen man deklariert eine Variable und initialisiert diese nicht direkt mit einem Wert.
Wir da überhaupt speicherplatz allokiert? Mir ist aufgefallen dass der Compiler nur ein Warning ausspuckt, initialisiert er beim kompilieren die Variable standardmässig mit einem Wert?

z.B. int i;

Wir Speicherplatz auf dem Stack allokiert?

Zum Thema OOP die selbe Frage.

ClassX varname;

Im Heap passiert ja nichts solange keine initialisierung per new() stattgefunden hat, steht in dem varname als referenz null (also Null-Pointer) oder passiert garnichts?

Ich hab noch ein paar Fragen, bin aber gespannt ob mir das jemand beantworten kann :D
 
Integer Variablen werden bei C# mit dem Wert 0 initialisiert.
 
Lokale tatsächlich auch? In Java z.B. werden nur Klassenattribute vorinitialisiert mit default Werten.
 
Bei der lokalen int-Variablen werden 4 Bytes auf dem Stack allokiert, außer der Compiler optimiert die unbenutzte lokale Variable weg.

Bei der Objektvariablen ist es ähnlich. Es wird Speicher reserviert, allerdings nicht auf dem Heap, wie du bereits sagtest. Es wird die Menge an Bytes, die für die Referenz benötigt werden, auf dem Stack allokiert. Bei der Objektvariablen handelt es sich nämlich auch nur um eine (lokale) Variable, die einen Wert speichert. Der Inhalt wird nur eben als Referenz auf das Objekt interpretiert. Die Menge an Bytes hängt dann davon ab, ob es eine 32 oder 64 Bit Architektur ist.

Was die Defaultwerte angeht, die Variablen werden mit 0 (int) bzw. null (Objektvariablen) initialisert. Bei der Warnung, die du erhälst handelt es sich eben auch nur um eine Warnung und nicht um einen Fehler. Das heißt das Programm wird kompiliert und du kannst mit der Variablen arbeiten. Und dann muss sie ja zwangsläufig irgendeinen Standardwert besitzen. Und bei C# ist der immer der Defaultwert des Datentyps.
 
Zuletzt bearbeitet:
Das Problem ist, dass VS einen Fehler ausspuckt

Verwendung der nicht zugewiesenen lokalen Variablen "blabla"

also wird standardmässig kein wert zugewiesen, d.h. auch kein speicherplatz im stack reserviert ?
 
Speicher aufm Stack wird für alle lokalen Variablen reserviert, solange die Variable nicht wegoptimiert wird. Aber da du bei einem Fehler sowieso nicht Compilieren kannst, wird sogesehen auch nichts reserviert, da dein Programm einfach nicht läuft ;)
 
ok eben gegenprobe gemacht,

ClassX varname1, varname2, varname3, varname4;

Prozessgrösse steigt (aber wieso schwankt der Wert nach mehrmaligem kompilieren Oo ?). Also scheint er tatsächlich platz von vornherein reservieren.
Ist die überlegung mit dem Null-Pointer halbwegs richtig ?

Etwas anspruchsvollere Frage:

Wir haben ein paar Objekte erzeugt (per new operator), jetzt liegen die dinger auf dem Heap, die Referenz (Pointer) liegt auf dem Stack. Wenn ich das richtig verstanden habe, wird beim anlegen des Objekts bei jeder Variable der this Zeiger (also Zeiger auf das Objekt selbst) hinterlegt.
Wie kommt man von der Referenz im Stack auf die Variable?
 
Zuletzt bearbeitet:
Wenn ich richtig versteh, was du meinst, dann kommst du an das Objekt im Heap durch die automatische Dereferenzierung, wenn du auf die Objektvariable, also die Referenz, zugreifst.
 
Problem ist, dass wir eine Referenz aufs komplette Objekt haben, wie komm ich über die Referenz an die public Variablen ?
 
Beim Dereferenzieren landest du im Speicherbereich des Objektes, also das was du gerade sagtest. Datenfelder einer Klasse besitzen ein bestimmtes Layout, d.h. eine Reihenfolge wie diese im Speicher liegen. Das legst du entweder selbst fest mit Attributen oder der Compiler macht das für dich. Dadurch und durch die Größen der einzelnen Datenfelder lässt sich damit die exakte Position so einer Variable im Speicher bestimmen. Angenommen du hast 2 Datenfelder vom Typ int (a und b). Dann ist es wahrscheinlich so, dass a im Speicher vor b liegt. Gibst du nun objekt.b ein, dann ist bekannt, dass es für das Datenfeld b ein Offset von 4 Bytes benötigt, weil davor nur das Datenfeld a liegt.
Im Speicherbereich eines Objektes liegt wird ja nur der Zustand des Objektes, also die Datenfelder. Deshalb werden dort auch die public (bzw eher private) Variablen gefunden.
 
Das klingt logisch :) Danke

noch eine Frage

beim überschreiben einer Methode (virtual -> override) haben wir ja zwei Methoden mit identischen Parametern im CodeBlock, wie funktioniert das genau im Speicher (vTable). base.Method ruft ja die Methode der Basisklasse auf, sonst die Methode des Objekts zu der entsprechenden Klasse.
 
Für virtuelle Methoden hat jede Klasse eine Tabelle. Zur Laufzeit wird bei der dynamischen Methodensuche in diesen Tabellen (entlang der Vererbungshierarchie) nach der ersten passenden Methode (richtige Signatur) gesucht. Die Suche beginnt dabei in der Klasse des dynamischen Typs des Objektes, also der Typ des Objektes, das zur Laufzeit in der Objektvariable referenziert wird.
Überschreibt eine Klasse eine Methode nicht, wird die Implementierung eben in einer der Baseklassen gefunden. Mit base.Methode() sorgst du eigentlich nur dafür, dass die Methodensuche fortgesetzt wird und die nächste passende Implementierung gesucht wird. Wegen diesen Tabellen sind virtuelle Methoden übrigens auch langsamer. Ist aber, solange du keine Anwendungen schreibst, die extrem Zeitkritisch sind, zu vernachlässigen.
 
Zurück
Oben