garbage collection - Referenzen finden und updaten



  • fdfdg schrieb:

    Ethon schrieb:

    Na, RAII ruft den Destruktor auf, der GC räumt den Speicher weg.

    Dann skizzier das mal. RAII läuft ja in C++ deshalb so gut, weil für Stackobjekte gut Code generiert werden kann, der nach Verlassen des Scopes aufgerufen wird.

    In C++ gibt es nur "automatic storage duration", wo der Speicher für solche Objekte herkommt ist nicht festgeschrieben. Natürlich ist der Standard dahingehend ausgelegt, Compilern zu ermöglichen den Stack dafür zu nutzen. Der Compiler könnte den Speicher aber genau so gut vom GC holen wenn er meint dass das schlau ist.
    Der Destruktor kann ja nach wie vor deterministisch beim Verlassen des Scope aufgerufen werden.

    Der Einsatz eines GC verträgt sich aber nicht gut mit der Nutzung des Stacks, deshalb hast du kein automatisches Aufräumen, ergo musst du herausfinden, welche Objekte nicht mehr gültig sind => Mark-And-Compact verliert seinen Vorteil.

    z.T. Stack siehe oben.

    Ansonsten...
    In Sprachen ohne GC musst du dafür sorgen, dass keine Referenzen auf Objekte die es nicht mehr gibt verwendet werden. Wenn man dabei einen Fehler macht, gibt es undefined behaviour. Das gilt für "non-RAII" Objekte und natürlich genau so für RAII-Objekte.

    Wenn du ein Programm nimmst das ohne GC korrekt funktioniert, und RAII einsetzt, dann wird es auch mit GC korrekt funktionieren und RAII einsetzen.

    Der einzige Unterschied ist dann, dass der Speicher der RAII Objekte erst später freigegeben wird. Der Aufruf des Destruktors bleibt dort wo er immer war. Man bekommt sogar noch einen Vorteil: die Referenzen (die man nicht haben/verwenden sollte) auf "freigegebene" Objekte zeigen jetzt nicht mehr ins Nirvana, sondern auf Objekte der jeweiligen Klasse die sich in einem (u.U. wohldefinierten) Zombie-Zustand befinden.
    Statt undefined behaviour kann man dann kontrolliert das Programm abbrechen (oder eine Exception werfen oder was auch immer).

    Probleme ergeben sich erst, wenn man vom GC jetzt zusätzlich noch fordert dass er deterministisch und ohne Verzögerung das "end of life" von Objekten mit shared ownership erkennt. Damit eben alle Objekte die Resourcen besitzen automatisch, deterministisch und sofort freigegeben werden können (wie man es z.B. von shared_ptr haben kann so lange man keine Zyklen baut). Das ist aber etwas was ein GC noch nie konnte, und was man auch vorher ohne GC nicht konnte. Die Forderung ist also unvernünftig.
    (Bzw. gleich gut wie shared_ptr kann es der GC natürlich können, Python macht das z.B. so (bzw. hat es zumindest in einigen Versionen so gemacht))

    Ansonsten... das ursprüngliche Thema war dass das ewige try-finally schreiben nervt, und das manuelle Aufrufen des Finalizers für Member nervt. Was jetzt mit dem GC wenig (nix) zu tun hat, sondern nur damit ob die Sprache die man verwendet eine Syntax dafür anbietet.

    z.B. in C++/CLI muss ich weder try-finally verwenden um Objekte mit "automatic storage duration" zu finalisieren, noch muss ich den Finalizer für Basisklassen oder Member manuell aufrufen.

    Wo ist jetzt also das Problem?

    fdfdg schrieb:

    Dieses blinde Argumentieren Pro-GC ist genauso dumm wie strikt dagegen zu reden. Einen GC einzusetzen bedeutet eben auch, entsprechende, teils starke, Nachteile hinzunehmen. Damit ist ein GC je nach Einsatzzweck "besser" oder "schlechter". Das wissen auch Shade und hustbaer, die müssen aber nunmal PI widersprechen.

    Ich argumentiere nicht "blind für GC".
    Wenn du wirklich meinst dass die Beiträge von Pi in dieser Diskussion irgend einen Wert haben, oder dass er nicht "strikt dagegen redet"... 🙄


Anmelden zum Antworten