![]() |
Delphi-Version: XE2
Verständnisfrage zu ARC
Hinweis: Es handelt sich um XE5, läßt sich hier aber nicht auswählen.
Ich habe eine zur Laufzeit erzeugte Firemonkey-Komponente. Die will ich von Zeit zu Zeit neu erzeugen. Bisher war ich es ja gewohnt, das mit Free oder FreeAndNil zu machen. Leider verschwindet die Komponente aber nicht. Erst mit DisposeOf. Das ist natürlich gefährlich, da man ja jahrelang so gearbeitet hat. Manchmal funktioniert es, manchmal nicht. Was muß man da für ein Pattern verwenden? Welche Schritte sind wann zu beachten.
Delphi-Quellcode:
interface
... TfrmDisplay = class(TForm) ... public Target : TTarget; Painter : TTargetPainter; CursorCircle : TEllipse; end; ... implementation ... procedure TfrmDisplay.Init; begin if Assigned(Target) then Target.Free; if Assigned(Painter) then Painter.Free; // Mit Free oder FreeAndNil bleibt die Komponente stehen und bei jedem // Aufruf der Init-Procedur kommt eine hinzu. if Assigned(CursorCircle) then CursorCircle.DisposeOf; ... CursorCircle := TEllipse.Create(ImageControl1); ... end; |
AW: Verständnisfrage zu ARC
Gehört die FMX-Komponente irgendwem? Wenn ja, dann müsstest Du dessen .RemoveObject()-Methode aufrufen. Danach kannst Du es dann freigeben.
|
AW: Verständnisfrage zu ARC
Ja, die gehört jemand. In dem Beispiel ein Imagecontrol. Nein, das muß ich nicht. Es verhält sich plattformabhängig! Bei einer Windows-Firemonkey-Anwendung verschwindet die Komponente durch das Free. Bei iOS z.b. nicht. Ich habe bei beiden das gleiche Framework, nämlich Firemonkey. "Nur" der Compiler ist unterschiedlich. Ich will eben so was vermeiden:
Delphi-Quellcode:
{$IFDEF NEXTGEN}
{$IFDEF ANDROID} Mist.DisposeOf {$ELSE} FreeAndNil(Mist) {$ENDIF} {$ELSE} Mist.Free; {$ELSE} |
AW: Verständnisfrage zu ARC
Aber sicher verhält es sich plattform-abhängig. Der Compiler für Win32 / Win64 hat doch gar kein ARC.
Der NEXTGEN-Compiler ersetzt einen Aufruf von .Free durch eine Zuweisung auf NIL. Ein .Free kannst Du damit für alle Compiler gleichermaßen verwenden, das IFDEF ist nicht erforderlich. Mit .DisposeOf() führst Du den Code aus, der im Destruktor des Objektes enthalten ist. Eine Freigabe erfolgt (allein) dadurch nicht. |
AW: Verständnisfrage zu ARC
Mir geht es um die Plattform-Unabhängigkeit. Die ist also erst dann gegeben, wenn ich Libaries, die jahrelang immer funktionierten, mit defines komplett überarbeiten muß? Weil u.U. das Free gar nix mehr tut...
|
AW: Verständnisfrage zu ARC
Das .Free löst eine Referenz auf ein Objekt auf und bewirkt, dass dessen Referenz-Zähler um eines nach unten geht. Ist dieser bei Null angekommen, so wird das Objekt unmittelbar an dieser Stelle freigegeben.
Und ja, es gibt bestimmt einige Bibliotheken, die unter Win32 anständig funktionieren, aber nicht ARC-fähig sind. |
AW: Verständnisfrage zu ARC
Durch das Zuweisen von Parent UND dem Setzen von Owner im Constructor wird also vermutlich der Referenzähler zweimal erhöht?
|
AW: Verständnisfrage zu ARC
Ja, allein ein Label auf einem Form hat 5 Referenzen. Parent, Owner, ein Styler, vielleicht ein Gesture-Manager - es kann viele Gründe dafür geben. Das ist nicht per se schlimm, so lange das Framework weiß, wann es was aufzuräumen hat. Deswegen ja mein Hinweis auf ".RemoveObject()". Dort werden genau diese Referenzen wieder aufgedröselt.
|
AW: Verständnisfrage zu ARC
Zitat:
Habe ich es richtig verstanden, dass
Delphi-Quellcode:
immer (gleich) funktionieren sollte, wenn nicht noch irgendwo andere Referenzen rumliegen, die man selbst zu verantworten zu hat :gruebel:
Mist.removeObject();
FreeAndNil(Mist); Das die Umstellung bzw. das Nebeneinander von manueller Speicherverwaltung und ARC nicht ohne Reibungsverluste funktioniert, ist irgendwie nicht wirklich überraschend. |
AW: Verständnisfrage zu ARC
Da werde ich wohl mal einige Versuche mit refcount machen. Ansonsten gilt wohl als Best Practice: Sämtliche Free durch DisposeOf ersetzen.
|
AW: Verständnisfrage zu ARC
Nein, das mit dem Free und DisposeOf haut nicht hin.
".DisposeOf" ändert den Referenz-Zähler nicht. Es führt lediglich den Code aus, der im Destruktor enthalten ist - degradiert damit den Destruktor fast zu einer normalen Methode. Das Objekt lebt danach noch - zumindest aus technischer Sicht, selbst wenn es fachlich vielleicht nicht mehr in der Lage sein mag, einer sinnvollen Tätigkeit nachzukommen. Zudem setzt .DisposeOf() ein Flag, das höchstwertige Bit des Referenz-Zählers. Danach hast Du auf jeden Fall ein RefCount von >= 2^32. Man spricht davon, dass das Objekt sich dann in einer Art "Zombie-Zustand" befindet. Ich zitiere mal aus dem DocWIKI: Ein Weg der Betrachtung der Unterschiede zwischen Free und DisposeOf liegt in der Berücksichtigung des Zwecks. Free wird zu dem Zweck verwendet, dass eine bestimmte Referenz von einer Instanz getrennt werden soll. Dabei ist eine Freigabe des Objekts oder von Speicher nicht impliziert. Im Gegensatz dazu teilt der Programmierer mit DisposeOf der Instanz explizit mit, "sich selbst zu bereinigen". Eine Speicherfreigabe ist dabei nicht notwendigerweise impliziert, DisposeOf führt eine explizite "Vorbereinigung" der Instanz durch. Anschließend ist die Instanz von der normalen Referenzzählungssemantik abhängig, die die Instanz dann schließlich freigeben kann. |
AW: Verständnisfrage zu ARC
Na dann bin ich ja froh dass ich jetzt weiss woher die fiesen Firemonkey-Speicherlecks kommen. Ich hab aber immer noch nicht verstanden wie ich Source wie z.b. in dem ersten Beitrag dieses Threads Mukltiplattformsicher bekomme - und das möglichst ohne Compiler-Defines wie NEXTGEN, AUTOREFCOUNT usw. abzufragen.
Konkretes Ziel war:
|
AW: Verständnisfrage zu ARC
Ich kann als reiner Windows-Kompilierer wahrscheinlich nicht wirklich mitreden. Aber ein
Delphi-Quellcode:
mittels
c:TControl
Delphi-Quellcode:
hinzufügen und später mittels
someParentControl.AddObject(c)
Delphi-Quellcode:
und anschließendem
RemoveObject(c)
Delphi-Quellcode:
zu entfernen ist doch eigentlich genau das richtige, oder?
c.Free()
Oder wird es komplizierter wenn bsp. der Owner von
Delphi-Quellcode:
ungleich
c
Delphi-Quellcode:
gewesen wäre?
someParentControl
|
AW: Verständnisfrage zu ARC
Sobald ARC im Spiel ist, läuft IMHO ein Free ins Leere (ein Blick in die Quellen liefert da Erkenntnis).
Mein Favorit wäre hier eigentlich ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:20 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz