Speicherverwaltung/Garbage Collector
-
Hallo,
ich habe eine einfache Frage zur Speicherverwaltung. Wir haben die folgende Klasse
ref class TolleKlasse{ System::String^ meinstr; public: TolleKlasse(){ meinstr= gcnew System::String("Hallo"); } void macheEtwas(){ meinstr= gcnew System::String("Servus"); } };
und erstellen davon ein Objekt und rufen macheEtwas() auf
Tolle Klasse^ tollesObjekt=gcnew TolleKlasse(); tollesObjekt->macheEtwas();
Was ist dann mit dem String "Hallo" passiert, der am Konstruktoraufruf erstellt wurde. Ist der dann schon gelöscht durch den Garbage Collector, oder hätte ich in macheEtwas ein delete Anweisung einbauen müssen um sicher zu gehen?
Viele Grüße,
mousepad
PS: Mir ist klar, dass dieses Beispiel mit Strings sinnlos ist. In meinem Fall sind es eben andere ref classes.
-
Hi,
eigentlich steht das "gc" ja für "garbage collector"
Aber das einfachste würde bestimmt sein es im Debugger auszuprobieren.
Also 1000 Mal macheEtwas aufrufen oder so und derweil im TaskManager den Speicherverbrauch anschauen.
Ich hatte nämlich schon das Problem, dass immer mehr Speicher reserviert wird und NICHT wieder freigegeben (zumindest sah es so aus)LG,
Dark
-
mousepad2 schrieb:
Was ist dann mit dem String "Hallo" passiert, der am Konstruktoraufruf erstellt wurde. Ist der dann schon gelöscht durch den Garbage Collector, oder hätte ich in macheEtwas ein delete Anweisung einbauen müssen um sicher zu gehen?
afaik - ist der String immer noch da ... wenn ich mich richtig erinnere ist der String sogar fest im Programm drinne ... Du kannst also an mehrere Stellen direkt "Hallo" zuweisen - es ist aber jedesmal die gleiche Referenz ... da Strings nicht geändert werden können (wenn Du was anhängst erhälst Du ja einen neuen String)
DarkShadow44 schrieb:
Also 1000 Mal macheEtwas aufrufen oder so und derweil im TaskManager den Speicherverbrauch anschauen.
Micro-Benchmarks sind unsinnig
Ich hatte nämlich schon das Problem, dass immer mehr Speicher reserviert wird und NICHT wieder freigegeben (zumindest sah es so aus)
das sah nicht nur so aus - das war auch so ... es macht keinen Sinn für 10 (?) bytes jedesmal den GC zu starten ... der verbraucht so mehr Zeit als wenn er alle 1000 Objekte mit einmal aufräumt (schon alleine der 1000-fache Context-Wechsel um den GC Thread zu starten ist aufwendig)
hand, mogel
-
Bei mir waren es aber Steuerelemente (Buttons/TextBox/...) die zur Laufzeit erzeugt wurden...
Da würde es sich schon lohnen aufzuräumen.
-
mogel schrieb:
afaik - ist der String immer noch da ... wenn ich mich richtig erinnere ist der String sogar fest im Programm drinne ... Du kannst also an mehrere Stellen direkt "Hallo" zuweisen - es ist aber jedesmal die gleiche Referenz ... da Strings nicht geändert werden können (wenn Du was anhängst erhälst Du ja einen neuen String)
Hallo, mir ist klar, dass "Hallo" "fest im Programm drin ist", d.h. nach dem Laden der exe, steht "Hallo" als Bytefolge irgendwo im Speicher des Programmcodes(kann man mit Disassembler anschauen). Schlechtes Beispiel. Aber zu anderen Objekten, die man so erzeugt, gehört ja noch etwas mehr dazu, was alles im dann im Speicher liegt. Was passiert dann damit?
-
Was damit passiert, ist, dass es *irgendwann mal* vom GC weggeräumt wird.
Bei Objekten die keine "unmanaged" Resourcen kontrollieren ist das auch vollkommen ausreichend.Bei Objekten die schon "unmanaged" Resourcen kontrollieren solltest du IDisposable.Dispose implementieren (Destruktor-Schreibweise, also ~Klassenname) und ggf. noch einen Finalizer (!Klassenname).
Und natürlich IDisposable.Dispose an den nötigen Stellen auch aufrufen, was man in C++/CLI mit "delete obj" macht.