C# Was passiert im Speicher beim Erstellen eines Objektes

no idea

Lt. Junior Grade
Registriert
Feb. 2004
Beiträge
452
Kann mir jemand beschreiben was im Speicher passiert beim erstellen eines neuen Objektes einer Klasse?

Also z.b. bei:

Class Klasse = new Class;

Was passiert genau bei "Class Klasse" und was bei "new Class";
WO wird der Speicher allokiert?
Was passiert im Heap, was im Stack?
Gibt es hierbei einen unterschied zwischen normalen Klassen und Datentypen, die ja auch nur eine Klasse sind?



Ich habe das anhand meiner sehr wenigen Quellen wie folgt verstanden:

"Class Klasse"
Im Heap wird ein NULL Zeiger erstellt.


"new Class"

1. Der Speicher im Stack für die Werte des Objektes werden allokiert. Gesamtgröße: 32/64bit
2. Der Heap Zeiger zeigt nun auf die Anfangsadresse des allokierten Speichers im Stack
3. Eine Instanz des Objektes wird erzeugt.
 
Zuletzt bearbeitet:
Die ersten beiden Punkte von "new Class" sind mit Sicherheit genau andersrum. Das "new" erzeugt ein neues Objekt im Heap und gibt einen Zeiger auf das Objekt zurück, der in der Variable "Klasse", die auf dem Stack liegt, gespeichert wird.

Eigentlich ist das, was du geschrieben hast, korrekt, wenn du die Begriffe "Stack" und "Heap" miteinander vertauschst.

Nachtrag: Punkt 1 ist eigentlich extrem unglücklich formuliert. Die Größe von 32 oder 64 Bit bezieht sich nicht auf die Werte des Objektes, sondern auf den Zeiger auf das Objekt. Ein Zeiger ist ja nach gängiger Architektur 4 oder 8 Byte groß (eben 32 oder 64 Bit).

Also nochmal in kurz: Das Objekt liegt auf dem Heap, auf dem Stack liegt nur ein Zeiger, der auf das Objekt im Heap verweist.

Nachtrag 2: Bevor mich nun jemand belehren wird, möchte ich selber noch erwähnen, dass man in C# auch Objekte auf dem Stack erzeugen kann (und zwar wenn man struct statt class verwendet). In C++ kann man auch primitive Datentypen auf den Heap legen. Ob das in C# auch geht, weiß ich leider nicht, da ich mich mit der Sprache nicht so gut auskenne.
 
Zuletzt bearbeitet:
wenn es gerade anderes herum bei "new class" sein müsste, dann müsste doch auch bei "Class Klass" anstelle von heap, Stack stehen oder?
 
Jawoll. Die Variable "Klass" wird auf dem Stack erstellt und kann einen Pointer auf ein Objekt vom Typ "Class" speichern.
 
no idea schrieb:
Kann mir jemand beschreiben was im Speicher passiert beim erstellen eines neuen Objektes einer Klasse?
Kann dir eigentlich ziemlich egal sein. C# läuft in einer VM mit jit, das heißt ggf. kann ein Objekt auch mal aus Optimierungsgründen auf dem Stack landen.

Wenn du dir über sowas den Kopf zerbrechen willst, nimm C++
 
ich frage bestimmt nicht aus spaß und das sind die überflüssigsten antworten
 
Kann man wohl nicht pauschal beantworten.
 
Zuletzt bearbeitet: (Vorherige Antwort war leider nicht korrekt.)
no idea schrieb:
ich frage bestimmt nicht aus spaß und das sind die überflüssigsten antworten
Lies einfach nochmal meine Antwort. Du hast keinen Einfluss darauf, wo wie welche Daten abgelegt werden. Insofern ist es müßig sich darüber Gedanken zu machen.
 
no idea schrieb:
Das ist leider alles hochgradig nichttrivial.

Die erste Angabe ist die Zahl für die „Stack“-Methode die laut deinem Artikel ja schneller sein sollte.
Code:
$ mono --optimize=-all bin/Release/Test1.exe 
50,6828
56,3465
In der Tat, schneller. Schalten wir mal alle Optimierungen ein.
Code:
$ mono --optimize=all bin/Release/Test1.exe 
4,9095
11,6216
nochmal deutlich schneller, wundert ja auch nicht, schließlich lässt sich die Methode mit den Argumenten wunderbar inlinen. Mal gucken was passiert, wenn man das ausschaltet.
Code:
$ mono --optimize=all,-inline bin/Release/Test1.exe 
38,0352
36,8109
Nanu? Langsamer, was ist jetzt passiert?

Sicherlich sind diese Tests alles andere als aussagekräfig, aber für das Fazit, dass man schon sehr genau wissen muss, was für Optimierungen die Laufzeitumgebung vornehmen kann um abschätzen zu können was passiert reicht es wohl.

Da hilft es wenig nur zu wissen, wie der Code zu Kompilierzeit aussieht und im Sinnes eines „premature optimization is the root of all evil.“ ist es wenig sinnvoll sich darüber zu viele Gedanken zu machen, so lange man keine konkreten Performanceprobleme hat.

Der Code für die Klasse Test ist der folgende:
Code:
namespace Test1
{
	public class Test
	{
		public int x = 2;
		public int y = 3;
		
		public int Add(int a, int b) {
			return a + b;
		}
		public int Add() {
			return x + y;
		}
	}
}
 
no idea schrieb:
ich frage bestimmt nicht aus spaß und das sind die überflüssigsten antworten
Wenn man schon soetwas von sich gibt, ist man vielleicht besser beraten, in den Sourcen der VM (z.B. mono) zu suchen als in einem Forum.

Man sollte keine Annahmen über das Laufzeit-Verhalten von Code machen, der JIT reinterpretiert und in nativen Code umgesetzt wird - das hat ja Darii in seinem letzten Post auch weiter ausgeführt.
Letztlich kommt es doch auf die Implementierung der VM an. Dein Code könnte auf der Windows-Implementierung für .NET schneller oder langsamer laufen als auf mono.
Ich persönlich mutmaße, dass VMs wie die von Java und .NET das Verhalten der auszuführenden Anwendungen analysieren (ob nun zur Laufzeit oder vor der Ausführung) um Geschwindigkeitsvorteile während der Ausführung zu erarbeiten.
 
Zurück
Oben