Garbage Collector



  • AlexanderKiebler schrieb:

    Hallo,

    Ich muß einen Garbage Collector schreiben.
    Wenn man von dieser Klasse ableitet,
    dann sollen durch einen funktionfaufruf alle mit new erzeugten Klassen zerstört werden, welche zuvor nich mit delete zerstört worden sind.
    Dies geschieht dadurch , dass ich in der Garbage Collector Klasse die operatoren new new[] delete delete[] überschreibe, und die
    so erhaltenen Pointer zwischenspeichere, oder bei einem Delete wieder aus der Liste nehme.

    Das ist eine nette Idee, aber kein Garbage Collector. Erinnert mich an die AutoReleasePools (oder so ähnlich) von Objective-C.

    Der wichtigste Unterschied zum Garbage Collector: Ein GC behält alle Objekte, die noch erreichbar sind. Du musst deinen "GC" triggern, wenn du selbst der Meinung bist, dass alle verwalteten Objekte nicht mehr erreichbar sind.

    Ich frag mich nun, woher kennt free die größe des frei zu gebenden Speichers ???

    Es speichert sich das intern irgendwie. Oder auch nicht. Das ist plattform- und compilerabhängig.



  • Hmm Okay.....
    Also einen vollständigen Garbage collector brauche ich dann nicht.
    Es soll so ablaufen:
    -Speichere alle mit new erzeugeten Pointer in ner Liste
    -Lösche alle mit delete zerstörten Objekte wieder aus der liste,
    -Sollten "zum Schluss"->single tone klasse zerstören, noch pointer in der Liste sein, derztöre die Objekte.

    Leider habe ich die Befürchtung, dass mir Delete nur
    den Speicherbereich der Größe sizeof( void 😉 frei gibt, und nicht den der gesamten klasse.

    Ich könnte ja mal nach schauen, aber wenns tatächlich compiler abhängig ist, hab ich schon en Problem...

    Gruß



  • AlexanderKiebler schrieb:

    Leider habe ich die Befürchtung, dass mir Delete nur
    den Speicherbereich der Größe sizeof( void 😉 frei gibt, und nicht den der gesamten klasse.

    free gibt schon den ganzen Speicher frei.



  • AlexanderKiebler schrieb:

    Es soll so ablaufen:
    -Speichere alle mit new erzeugeten Pointer in ner Liste
    -Lösche alle mit delete zerstörten Objekte wieder aus der liste,
    -Sollten "zum Schluss"->single tone klasse zerstören, noch pointer in der Liste sein, derztöre die Objekte.

    Das läuft allen etablierten C++-Praktiken entgegen. Warum musst du das machen? Soll das einen praktischen Nutzen haben?



  • Nukularfüsiker schrieb:

    AlexanderKiebler schrieb:

    Es soll so ablaufen:
    -Speichere alle mit new erzeugeten Pointer in ner Liste
    -Lösche alle mit delete zerstörten Objekte wieder aus der liste,
    -Sollten "zum Schluss"->single tone klasse zerstören, noch pointer in der Liste sein, derztöre die Objekte.

    Das läuft allen etablierten C++-Praktiken entgegen. Warum musst du das machen? Soll das einen praktischen Nutzen haben? Ist der Auftraggeber ein Idiot?

    Vielleicht will der Herr Auftraggeber nur, dass sich die Herrn Lernenden mit dem Thema beschäftigen und den Hintergrund verstehen?

    MfG SideWinder



  • SideWinder schrieb:

    Vielleicht will der Herr Auftraggeber nur, dass sich die Herrn Lernenden mit dem Thema beschäftigen und den Hintergrund verstehen?

    So entstehen schlechte C++-Programmierer.



  • Hi nochmal,

    Das Problem ist das Folgende:

    -Es gibt ne Single Tone Klasse welche als Zeit Trigger funktioniert.
    -Es gibt Eine virtuelle Simulationsklasse, über welche die Zeit Klasse
    mit den Simulationsblöcken kommuniziert.
    -Dann gibt es eine GUI Bibliothek welche die Einsprungsfunktion (main)
    bereitstellt. (wxWidgets)
    -Es gibt nun einen Funktionsaufruf void MY_MAIN(void), in dem alle
    Simulationsblöcke erzeugt werden sollen.
    (Simulationsblöcke geben zum Beispiel ein Sinussignal aus, oder sie lesen daten von einem verbunden block und schreiben in einen verbundenen Block und sie können natürlich in dem Rechenzyklus Daten berechnen. Zum Beispiel eine lineare Differenzialgleichung)
    -Wenn ich die Simulationsblöcke nicht als pointer anfordere, werden sie automatisch wieder beim Verlassen von MY_MAIN(void) gelöscht.
    -Ich könne jetzt natürlich eine Destruktorähnliche Funktion
    MY_MAIN_DESTRUKT(void)
    machen, aber die so erzeugten Pointer müßt ich so oder so zwischen speichern.
    Und dann jedes mal wieder die objekte zerstören ??? Das kann ich doch gleich automatisch machen lassen und dem Anwender programmierer das ganzeersparen.

    Der von mir gewählte Weg funktioniert um ehrlich zu sein super gut, und ich sehe kein Problem mehr, wenn delete immer den gesamten Speicher freigibt.
    Also vom Konzept herkann ich eigentlich nciht meckern.

    Würd ich allerdings sehr freuen, wenn ich noch den Aufbau von einem C/C++ Pointer irgendwoher bekommen könne.

    Also welche Daten werden wo gespeichert ??

    Gruß Alex



  • @Nukularfüsiker

    Wenn du dich mit dem Problem so gut auskennst, hast du dich damit also auch befasst ??
    Ergo du bist nach deiner Aussage ein schlechter Programmierer geworden was C++ an geht ??
    Wiso sollt ich dann auf dich hören ??

    Ode du hast dich noch nicht damit befasst ???
    -> Wiso sollt ich dann auf dich hören ???

    Ratschläge sind ja gut, aber sie sollten doch eher ohne Wertung auf die Persohn stattfinden.
    Es. so entsteht schlechter C++ code, wenn das dine Meinung sit, aber nicht gleich der ganze Programmierer 😉

    Gruß



  • AlexanderKiebler schrieb:

    Also welche Daten werden wo gespeichert ??

    Adresse des Speicherbereichs im Pointer. Ende.



  • AlexanderKiebler schrieb:

    Wenn du dich mit dem Problem so gut auskennst, hast du dich damit also auch befasst ??

    Ja.

    Ergo du bist nach deiner Aussage ein schlechter Programmierer geworden was C++ an geht ??

    Nein. Eher so Mittelmaß. Aber ich habe genug Erfahrung und lange mit "Spezialisten" zusammengearbeit, um Mist zu erkennen.

    Wiso sollt ich dann auf dich hören ??

    Brauchst du doch nicht.

    Ratschläge sind ja gut, aber sie sollten doch eher ohne Wertung auf die Persohn stattfinden.

    Leg dir mal ein dickeres Fell zu. Du hast ein Problem mit C++, du kriegst Antworten darauf. Nicht jede dieser Antworten muss dir gefallen.

    Wenn dich das "Idiot" persönlich getroffen hat, entschuldige ich mich für die Bezeichnung und ändere es hiermit in "Ahnungsloser".



  • Wie würdest du denn das Problem angehen ??
    P.s.: Würd mich über ne Antwort ohne Beschimpfung freuen 🙂



  • Ich werde aus deiner Beschreibung nicht so recht schlau und bin mir deshalb nicht sicher was genau das Problem ist.

    Generell würde ich sagen: Speicherverwaltung in C++ ist einfach, wenn man zwei einfache Grundsätze befolgt:
    1. Der Teil des Programms, der den Speicher anfordert, gibt ihn auch wieder frei.
    2. RAII funktioniert (fast) immer.

    Alles was hiervon abweicht, ist erst mal komisch und sollte gut begründet werden.



  • AlexanderKiebler schrieb:

    Wie würdest du denn das Problem angehen ??

    Da es eh eine Möglichkeit geben muß, herauszufinden, welche Objekte noch leben, also auf welche Objekte noch Zeiger zeigen, müssen die Zeiger selber smart werden. Ich denke mal, gegen dieses Argument kannste keinen Ausweg finden.
    Und dann kannste auch den Großteil der Mitzähl-Und-Aufräum-Logik in die smart pointers legen. Wenn GC-Objekte eh von der Basisklasse GarbageCollect erben müssen, was eine sehr gute Idee ist, brauchste vielleicht gar nicht an new/delete zu fummeln, dann kannste den refcounter oder die Verkettungszeiger vielleicht in der Basisklasse lassen. Draußen wäre vielleicht lecker, um mal eine XOR-Liste auszuprobieren.



  • Ich verstehe das Problem noch nicht ganz. Während einer Simulation werden also dynamisch Objekte erzeugt, die -- wahrscheinlich -- ein paar Zeitschritte überleben sollen und dann irgendwann wieder zerstört werden sollen. Richtig soweit? Warum siehst Du dich jetzt gezwungen, einen GC nachzubauen?



  • Hi Volkard,

    Erstmal Danke Für die Antwort. 🙂
    Also

    Da es eh eine Möglichkeit geben muß, herauszufinden, welche Objekte noch leben, also auf welche Objekte noch Zeiger zeigen, müssen die Zeiger selber smart werden.

    Ich hab mir das gerade mal durchgeguckt. Also die Smart Pointer von Boost.
    Ich persöhnlich halte das ein bischen für "mit Kanonen auf Spatzen geschossen"

    Testen auf:
    -Gibt es noch einen Pointer auf das Objekt
    Zum auslösen von delete ist schon mehr als ich jetzt wollte.

    Was ist denn so schlecht daran einfach new und delete zu überladen ??
    Ist das geächtet wie goto ??

    In der Funktion
    MY_MAIN(void)
    kann man dann so programmieren wie immer. Nur wenn zufällig ein Pointer nicht aufgeräumt wird, wird das eben automatisch erledigt.

    Ich sehe bei meiner vorgehensweise eigentlich kein Problem.

    Wobei cih das mit den Smart pointern sehr schlau finde =).



  • @krümel

    Also gezwungen nicht. Aber es wäre eben schön.
    Die Simulationsblöcke sollen alle in einer Funktion
    MY_MAIN(void)
    erzeugt werden.
    Damit sie nach dem Verlassen der Funktion noch existiern sollte das Dynamisch geschehen.
    Jeder Simulationsblock lebt bis zum Ende der Simulation.
    Und dann sollen sie aber zerstört werden.

    Ich glaube das Wort Garbage Collector ist etwas hochgegriffen gewesen von meiner Seite.
    Der soll ja eigentlich prüfen ob noch ein Pointer auf die Instanz vorhanden ist. Und wennn nein, dann soll er das Objekt zerstören.
    Das brauch ich garnicht.
    Ich muss einfach alles was in der Funktion
    MY_MAIN(void)
    dynamisch erzeugt, und nicht mit delete zerstört worden ist dannach aufräume.
    Wobei cih davon ausgehen darf, dass in dieser Funktion alle Objekte von
    der Simulationsklass und damit von der Garbage Collect klasse erben.



  • Ein Problem dabei ist, dass C++ dem Programmierer ein bestimmtes Verhalten zusagt. Dazu gehört, dass ein mit new geholter Pointer bis zum delete gültig bleibt. Du greifst mit deinem Konzept in dieses System ein und setzt damit den gesamten C++-Standard außer Kraft. Wenn mal jemand dein System benutzt, der mehr von C++ versteht als du, der wird dich verfluchen.

    Außerdem ist es eine üble Sache, Programmierfehler zu verstecken. Du bekämpfst damit Symptome schlampiger Programmierung, statt die Ursache zu beheben. Gib statt dessen eine fette Fehlermeldung aus, das macht es ein klein wenig besser (aber immer noch nicht gut).

    Und dann die ganzen Fallen. Es gibt Geschichten wie placement new, die dir hier in die Suppe spucken könnten. Möglicherweise weißt du nicht einmal, was das überhaupt ist - das wäre dann ein sicheres Zeichen für dich, nicht in der Speicherverwaltung rumzupfuschen.
    Und natürliche globale Objekte, die im Destruktor selbst ein delete machen, wobei dein Gehacke sofort übelst krachen geht, mit einem Programmabsturz, dessen Ursache kaum zu finden ist.



  • Also zunächst bleib ich dem verhalten von C++ treu, soweit es ein GUI programmierer kennt. Das passt eigentlich schon.
    Der Programmierer Darf zerstören, muss aber nicht, so wie in den Meißten Bibliotheken.

    Ein Placement new würd ich hier jetzt nicht implementieren.
    Das wäre eher interessante, wenn ich zeitkritisch was alloziieren möchte,
    oder auch für objekte in Shared Memory könnt ich mir das vorstellen.
    Placement new wird bei mir nicht vorkommen.

    Gruß



  • AlexanderKiebler schrieb:

    Also zunächst bleib ich dem verhalten von C++ treu, soweit es ein GUI programmierer kennt. Das passt eigentlich schon.

    ...was soll man auf solche Ignoranz noch antworten? Du bleibst damit dem Verhalten von C++ ungefähr so treu, wie dein Geschreibsel der Deutschen Rechtschreibung treu bleibt. Also quasi überhaupt nicht.

    Der Programmierer Darf zerstören, muss aber nicht, so wie in den Meißten Bibliotheken.

    Doch, der Programmierer muss, weil er korrekt programmieren soll. Und wenn du ihm in die Quere kommst, dann darf er eben nicht mehr. Siehe globale Objekte.

    Ein Placement new würd ich hier jetzt nicht implementieren.

    Ach.

    Ich lasse es mal gut sein hier in dem Thread. Vielleicht findet ein anderer bessere Argumente, die du verstehen kannst 🙂



  • AlexanderKiebler schrieb:

    Ich hab mir das gerade mal durchgeguckt. Also die Smart Pointer von Boost.
    Ich persöhnlich halte das ein bischen für "mit Kanonen auf Spatzen geschossen"

    Du musst bei einem GC ja auch darüber eine Liste führen, wenn der Zeiger noch verwendet wird, und dies geht nur mittels Mechanismen wie Referenzzählung. Zudem ist der shared_ptr, obwohl ein Schwergewicht (Den ich nur bei geteilten Ressourcen verwenden würde), auch in der Lage gegenseitige Objektverweise aufzulösen (Stichwort: weak_ptr). Mal sehen wie du das ohne den Aufwand nachbasteln willst.

    GC und C++ vertragen sich wirklich nicht, zumindest nicht, wenn nicht Auflagen zur Verwendung oder noch besser der Compiler eine Lösung unter der Haube einbaut (Ist ja durchaus "optional" in Überlegung für einen späteren Technical Report).


Anmelden zum Antworten