Garbage Collector
-
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.void *GarbageCollect::operator new(size_t size)throw() { if(void* ptr=malloc(size)) { static_cast<GarbageCollect*>(ptr)->this_ptr.insert(ptr); return ptr; } return NULL; }Das delete gibt dann den Speicher mit free wieder frei.
Ich frag mich nun, woher kennt free die größe des frei zu gebenden Speichers ???Gruß Alex
-
AlexanderKiebler schrieb:
Ich muß einen Garbage Collector schreiben.
So ein Unfug. Sag dem Auftraggeber, er soll programmieren lernen und sich RAII anschauen.
AlexanderKiebler schrieb:
Ich frag mich nun, woher kennt free die größe des frei zu gebenden Speichers ???
free speichert selber die Größe. Aber vielleicht nicht aufs Byte genau. Gerade genug, um den Speicher wieder freigeben zu können. Wobei der Speicher auch ein bißchen zu viel gewesen sein könnte, das ist in C ja keine Schande.
Genauer kriegste die Größe von delete. Und das weiß es vom zu löschenden Typen. Wobei gerne ein wenig Größeninformation in die vtbl geschrieben werdne darf. Der Compilerbauer hat viele Möglichkeiten, Compilermagie einzubauen, die wir nicht erreichen können. Du benutzt dazu doch den operator delete(void*,size_t) für diese Schnapsidee? Falls nicht, solltest Du ernsthaft darüber nachdenken, falls die Größe für Dich von interesse ist. Sollte aber gar nicht von Interesse sein, außer Du baust auch small object allocators oder so. Obwohl, wer einen GC bauen will, der will auch einen Schutzbereich dranhängen.
-
AlexanderKiebler schrieb:
Ich muß einen Garbage Collector schreiben.
Aha.

AlexanderKiebler schrieb:
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.
AlexanderKiebler schrieb:
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.new[] und delete[] soll man doch gar nicht benutzen, da zu "low level". Stephan T. Lavavej hat das mal als nette Daumenregel hier formuliert:
Nacktes new/delete sollte man zugunsten von shared_ptr und unique_ptr vermeiden.
Nacktes new[]/delete[] sollte man zugunsten der Standardcontainer vermeiden.Gut, shared_ptr/unique_ptr sind noch nicht offizieller Bestandteil des C++ Standards. Aber das wird noch.
AlexanderKiebler schrieb:
void *GarbageCollect::operator new(size_t size)throw() { if(void* ptr=malloc(size)) { static_cast<GarbageCollect*>(ptr)->this_ptr.insert(ptr); return ptr; } return NULL; }Herzlichen Glückwunsch. Du greifst auf ein Datenelement (this_ptr) eines noch nicht initialisierten Objekts zurück.

AlexanderKiebler schrieb:
Das delete gibt dann den Speicher mit free wieder frei.
Ich frag mich nun, woher kennt free die größe des frei zu gebenden Speichers ???Na, die Größe wird irgendwo von irgendwem gespeichert. Ist das wichtig?
kk
-
Das hört sich ja toll an 
malloc gibt ja den Typen void * zurück.
Genau in in diesem typen speichere ich auch die Pointer.Zerstört ein Delete nun den Bereich
sizeof(void
oder den gesamten Speicherbereich ??Wiso soll das eigentlich ne Schnaps Idee sein ??
Ich finde das garnicht so schlecht.Gruß Alex
-
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
-
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.

AlsoDa 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 =).
-
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.