Garbage Collection

    Garbage Collection

    Hallo zusammen,

    Existiert wirklich KEINERLEI Garbage Collection in Delphi?

    Falls ja: Gibt es eine elegante Möglichkeit, dass Objekte automatisch entfernt werden, sobald es keine Referenz mehr auf sie gibt?

    Falls nein: Wann genau werden Objekte Garbage-Collected?
    Sind folgende Fälle enthalten?
    - Das Objekt ist ein Attribut eines anderen Objekts, das gelöscht wurde
    - Das Objekt wurde anonym erstellt (also z.B.

    Delphi-Code

    1. interface
    2. type TObjekt = class
    3. attribut: integer;
    4. end;
    5. //Diese Funktion erstellt ein neues Objekt vom Typ TObjekt und gibt "attribut" irgendeinen Wert
    6. function neuesObjekt(wert1, wert2, wert3): TObjekt;
    7. implementation
    8. // [...]
    9. if (neuesObjekt(x, y, z).attribut = attributWert) then
    10. //[...]

    ...und nach der If-Abfrage wird das bei der Abfrage erstelle Objekt nie mehr verwendet)
    - Procedure/Function wurde vollständig ausgeführt. Das Objekt ist in einer lokalen Variable gespeichert und weder Parameter noch Rückgabewert

    Beste Grüße,
    fsmman
    Hi fsmman

    Wenn du deinem 'Neuen Object' einen Eigentümer zuweist(zB. TComponent oder TMainform), gibt dieser dein neues Object frei, sobald er selber freigegeben wird.
    Es gibt aber auch Ausnahmefälle, wenn Objekte bei der Erzeugung kein Eigentümer zugewiesen werden kann.

    Wenn du zB. eine Paintbox verwendest, hat diese das Objekt-Property Canvas, dessen Owner die Paintbox ist. Mit den Eigenschaften Paintbox.Canvas.Pen und Paintbox.Canvas.Brush ist es (beinahe) das selbe, nur das hier nicht die Paintbox sondern der Canvas der Paintbox der Eigentümer ist.
    Aber vorsicht: Wenn du TPen oder TBrush ausserhalb der Paintbox (oder eines TImage) verwendest und erzeugst, haben diese Objekte vorerst keinen Eigentümer, können von diesem also auch nicht freigegeben werden!!

    - Das Objekt ist ein Attribut eines anderen Objekts, das gelöscht wurde
    - Das Objekt wurde anonym erstellt (also z.B.


    Zu:
    1. Wenn du ein eigenes Objekt hast, das andere Objekte als Propertys verwendet, musst du diese Objektpropertys beim Erstellen deines eigenen Objektes createn. Gibst du nun deinen Ojektpropertys als Owner dein eigenes Objekt, so sorgt dieses für die Freigabe der Objektpropertys, sobald es selbst freigegeben wird. Wenn nicht, musst du die Ojektpropertys selbst freigeben.
    2. Dito. Der Owner kann zB die Mainform oder Self sein. Self bezeichnet immer das übergeordnete Objekt (zB. TForm, TFrame aber mW. nicht TPanel)
    Des weiteren:

    fsmman schrieb:

    ..und nach der If-Abfrage wird das bei der Abfrage erstelle Objekt nie mehr verwendet)

    Ich würds mal so sagen: Unmögliches wird sofort erledigt, Wunder dauern etwas länger.

    Aber Spass beiseite: Delphi erkennt nicht, dass das Objekt im weiteren Programmverlauf nicht mehr benötigt wird und löscht es deshalb nicht.

    fsmman schrieb:

    - Procedure/Function wurde vollständig ausgeführt. Das Objekt ist in einer lokalen Variable gespeichert und weder Parameter noch Rückgabewert

    Grundsätzlich müssen lokale Variablen nicht freigegeben werden, da sie nur während des Prozedurablaufs gültig sind. Es sei denn, es wird explizit Speicher reserviert, wie das beim Erzeugen eines Objektes der fall ist.
    Da gibts mehrere Möglichkeiten:
    • Du deklarierst und erzeugst dein Objekt in einer Prozedur, arbeitest damit und gibst es vor verlassen der Prozedur wieder frei.
    • Oder du deklarierst ein privates Feld deiner Form/deines Frames, erzeugst das hier benötigte Object im Constructor/bei OnCreate und gibst es im Destructor/bei OnDestroy wieder frei
    Wirklich Zaubern kann nicht mal Delphi...

    Gruss
    Delbor
    roase.ch/

    Was wirklich zählt, ist Intuition. Albert Einstein

    ________________

    Delbor alias Zoran

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Delbor“ ()

    fsmman schrieb:


    Falls ja: Gibt es eine elegante Möglichkeit, dass Objekte automatisch entfernt werden, sobald es keine Referenz mehr auf sie gibt?

    Spricht was gegen Interfaces ?
    Glückauf

    Herr, wirf Hirn vom Himmel

    Ein Leben ohne Möpse ist möglich, aber sinnlos ( Loriot )
    Der beste Platz für Politiker ist das Wahlplakat. Dort ist er tragbar, geräuschlos und leicht zu entfernen ( Loriot )

    Es gibt Leute, die fühlen sich überall gedemütigt, wo sie nicht frech sein dürfen ( Otto Weiss )
    Das mit dem Eigentümer gilt nur für Komponenten, also Nachfahren von TComponent. Man könnte vielleicht etwas mit Interfaces machen, aber dazu müsste ich den Zweck der Übung erst einmal begreifen, mir ist nämlich nicht klar, was Du mit diesem Attributvergleich erreichen willst. Vielleicht brauchst Du ja gar keine Klassen, sondern wärst mit einem Record schon gut bedient.
    10 Minuten Nachdenken ersparen oftmals 10 Stunden Fehlersuche.
    OK erstmal Danke für die Rückmeldung. Das bedeutet, dass ich besser selber schauen sollte, dass auch alle Elemente freigegeben werden.

    Wobei es hier geht: Einfach gesagt möchte ich einen String in eine Baumstruktur umwandeln, ahnand derer einzelne Eigenschaften des Strings ermittelt werden. Leider ist dabei die Verwendung von Klassen aus meiner Sicht unumgänglich, einfach gesagt deswegen, weil es unterschiedliche Knoten-Arten innerhalb des Baums gibt und daher Vererbung erforderlich wird. Weiter werden einzelne Attribute dieser Klassen von TObjectList abgeleitet und insofern würde das auch keinen Sinn machen, mit Records zu arbeiten.

    Was mir nicht ganz klar ist, ist inwiefern Interfaces mein Problem lösen. Da hat mir leider der Eintrag auf DelphiTreff nicht wirklich geholfen.
    Machen wir doch einmal ein simples Beispiel mit 2 Klassen, eine davon "normal", die andere implementiert ein Interface und wird von TInterfacedObject abgeleitet:

    Delphi-Code

    1. type
    2. TNonInterfaced = class
    3. procedure TuWas;
    4. end;
    5. ISomeInterface = interface
    6. ['{EB9C2088-9046-4DBA-A0EB-D45A22599EE0}']
    7. procedure TuWas;
    8. end;
    9. TInterfacedClass = class(TInterfacedObject, ISomeInterface)
    10. procedure TuWas;
    11. end;
    12. { TNonInterfaced }
    13. procedure TNonInterfaced.TuWas;
    14. begin
    15. ShowMessage('Ohne Interface');
    16. end;
    17. { TInterfacedClass }
    18. procedure TInterfacedClass.TuWas;
    19. begin
    20. ShowMessage('Mit Interface');
    21. end;

    Jetzt pappen wir 2 Buttons auf das Formular, die beide etwas ähnliches tun: Erzeugen einer Instanz und Nutzung derselben. Nur benutzt der eine dafür die "normale" Klasse, der andere das Interface:

    Delphi-Code

    1. procedure TfrmIntfDemo.btnInterfacedClassClick(Sender: TObject);
    2. var
    3. //Wichtig: Typ der Variablen ist das Interface
    4. tmp: ISomeInterface;
    5. begin
    6. tmp := TInterfacedClass.Create;
    7. tmp.TuWas;
    8. end;
    9. procedure TfrmIntfDemo.btnSimpleClassClick(Sender: TObject);
    10. var
    11. tmp: TNonInterfaced;
    12. begin
    13. tmp := TNonInterfaced.Create;
    14. tmp.TuWas;
    15. end;

    Einer der beiden erzeugt ein Speicherleck, der andere aber nicht, das kann man mit ReportMemoryLeaksOnShutdown einfach überprüfen.
    10 Minuten Nachdenken ersparen oftmals 10 Stunden Fehlersuche.
    Moin... 8o
    Da du nur D2010 hast, sind Generics nicht möglich. ;( Da hättest du eine TObjectList<TBlubb> zur Verfügung. Kannst du auf ein aktuelles Delphi wechseln? Ist die aktuelle Delphi Starter eine Option? :thumbup:

    TInterfaceList böte sich doch da an.

    ...die hatte ich übersehen. 8|