Garbage Collector



  • Hi,

    ich versuche gerade einen Garbage Collector zu schreiben. Nach ein Paar Stunden Überlegungen, Fehlversuchen und Schnittstellendesign, bin ich zu der Erkenntnis gekommen, dass alle Objekte dynamisch erzeugt werden müssen, wenn sie der Garbage Collector kennen sollte. Dazu hab ich dann eine Klasse geschreiben, von der alle anderen ableiten müssen, aber ich bin mir nicht sicher ob sie immer funktioniert. Könnt ihr mir da weiterhelfen?

    Hier der Quelltext dazu:

    //---------------------------------------------------------------------------
    //: Das Objekt kann nur dynamisch erzeugt werden, sonst bekommt man zur
    //- Laufzeit eine ENotDynamic-Aunahme
    class CDynamicObject
    {
    private:
       static CDynamicObject *lastPointer;
    public:
       class ENotDynamic: public exception{
       public:
          explicit ENotDynamic(): exception() {};
       };
       CDynamicObject(){
          if (lastPointer != this)
              throw ENotDynamic();
       };
       void *operator new(size_t size){
          lastPointer = static_cast<CDynamicObject*>( ::operator new (size) );
          return lastPointer;
       };
       void *operator new[](size_t size){
          lastPointer = static_cast<CDynamicObject*>( ::operator new[](size) );
          return lastPointer;
       };
    };
    CDynamicObject *CDynamicObject::lastPointer = NULL;
    //---------------------------------------------------------------------------
    

    Ich denke wenn ein dynamisches Objekt zerstört wird (vom GC oder manuel) und danach ein statisches Objekt erzeugt wird, dass es dann auf den Speicher des zerstörten Objekts zeigt, und deswegen der Ausdruck (lastPointer == this) stimmt. Oder stimmt es nicht? Gibt es vielleicht noch eine portable Möglichkeit wie es zur Kompilierzeit erkannt werden kann ob das Objekt statisch oder dynamisch erzeugt wurde. Bei den VCL-Klassen funktioniert es ja irgendwie.

    Die zweite Frage wäre dann auf den Garbage Collector bezogen. Wie kann ich feststellen ob ein Zeiger auf einen gültigen Speicherbereich zeigt oder nicht? Wird es funktionieren wenn ich den delete Operator des CDynamicObject überschreibe und dann den Zeiger nach dem Aufruf von free() den Wert NULL zuweise?



  • Hallo,
    erstmal:
    http://www.hpl.hp.com/personal/Hans_Boehm/gc/

    Gibt es vielleicht noch eine portable Möglichkeit wie es zur Kompilierzeit erkannt werden kann ob das Objekt statisch oder dynamisch erzeugt wurde

    Es gibt imo überhaupt keine portable Möglichkeit dafür.

    Wie kann ich feststellen ob ein Zeiger auf einen gültigen Speicherbereich zeigt oder nicht?

    Für den allgemeinen Fall überhaupt nicht.

    Wird es funktionieren wenn ich den delete Operator des CDynamicObject überschreibe und dann den Zeiger nach dem Aufruf von free() den Wert NULL zuweise?

    Dann kannst du danach prüfen, ob der Zeiger != dem Nullzeiger ist. Mehr aber auch nicht.

    Was du natürlich z.B. machen könntest ist eine Mixin-Klasse, die die operatoren new/delete überlädt. Im op new wird der Pointer in einer Map gespeichert. Im op delete kann dann geprüft werden, ob der Pointer in der Map existiert.
    Eine genaue Beschreibung dieser Technik samt Implementation findest du z.B. in Scott Meyers "More Effective C++" Item 27



  • Welche GC-Technik willst du eigentlich verwenden?



  • Wenn es darum geht Objekte automatisch zu löschen, wenn sie ihren Gültigkeitsbereich verlassen haben, kann ich Dir nur empfehlen Dir die Arbeit zu sparen, auf jeden Fall für einen kommerziellen Bedarf. Hierzu gibt es die auto_ptr oder shared_ptr. Für persönliche Erfahrungen sich mit sowas zu befassen, ist es sicherlich sehr interessant und hilfreich.

    Gruß
    Gerhard



  • Bashar schrieb:

    Welche GC-Technik willst du eigentlich verwenden?

    Ich kenne mich in verschiedenen Techniken nicht aus, aber ich hab es mir so überlegt:
    ich hab eine Klasse (GC), diese betreibt eine Liste von Zeigern auf Objekte, die von CDynamicObject abgeleitet sind (in etwas vereinfachter Version siehe oben). Diese Objekte "registrieren" sich selbst beim Aufruf des Operators new bei GC. Da ich nicht weiß (und es geht auch wahrscheinlich nicht), wie man feststellen kann ob die Variable ihren Gültigkeitsbereich verlies, um diese dann freizugeben. So gibt der GC - beim beenden des Programms - den Speicher für jede Variable, die noch nicht gelöscht wurde (vergleichen von Pointer != NULL) frei. Aber es ist mir im Moment zu kompliziert geworden, deswegen progge ich es nicht weiter. :p Zum Beispiel wird da der Destruktor von den von CDynamicObject abgeleiteten Klassen nicht aufgerufen, nur vom CDynamicObject.

    Eine andere Möglichkeit, die ich mir überlegt habe, war dass zu jeder dynamisch erzeugten Variablen eine Statische ezeugt wird, die dann nach dem ihr Destruktor aufgerufen wird auch den Speicher der dynamischen Variable freigibt. Aber auch hier tritt das obengenannte Problem auf.



  • Gerhard schrieb:

    Wenn es darum geht Objekte automatisch zu löschen, wenn sie ihren Gültigkeitsbereich verlassen haben, kann ich Dir nur empfehlen Dir die Arbeit zu sparen, auf jeden Fall für einen kommerziellen Bedarf. Hierzu gibt es die auto_ptr oder shared_ptr. Für persönliche Erfahrungen sich mit sowas zu befassen, ist es sicherlich sehr interessant und hilfreich.

    Gruß
    Gerhard

    Es ist nur um etwas Erfahrung damit zu sammeln. Aber da du schon die auto_ptr bzw. shared_ptr erwähnst, werde ich mich jetzt 'ne weile damit befassen.



  • bIce schrieb:

    Ich denke wenn ein dynamisches Objekt zerstört wird (vom GC oder manuel) und danach ein statisches Objekt erzeugt wird, dass es dann auf den Speicher des zerstörten Objekts zeigt, und deswegen der Ausdruck (lastPointer == this) stimmt. Oder stimmt es nicht?

    Kann mir jemand dazu noch was sagen?



  • wie soll "danach" ein statisches Objekt erzeugt werden? Statische Objekte heißen statisch, weil sie während der gesamten Ablaufzeit des Programms, von Anfang bis Ende existieren.



  • Ich hab wohl das Wort "statisch" hier falsch verwendet. Ich meine es so:

    Ein_Objekt_von_CDynamicObject * obj = new Ein_Objekt_von_CDynamicObject;
    Das_andere_Objekt dao(obj); // < dies hier habe ich als statischerzeugtes bezeichnet
    

Anmelden zum Antworten