Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Cross-Platform-Entwicklung (https://www.delphipraxis.net/91-cross-platform-entwicklung/)
-   -   Delphi Weak Referenzen überlegungen... (https://www.delphipraxis.net/183272-weak-referenzen-ueberlegungen.html)

Mavarik 26. Dez 2014 13:38

Weak Referenzen überlegungen...
 
Hallo Zusammen...

Vor ARC haben wir uns keine sorgen gemacht, oder?
Es wurde eine Objekt erzeugt und wenn wir es nicht mehr gebraucht haben, wurde einfach ein Free aufgerufen.

Dann wurden wir plötzlich entmündigt und ein Free machte nix mehr...

Besonders Fatal bei Sourcecode wo wir uns darauf verlassen haben, dass ein Free auch Freeed...:stupid:

Delphi-Quellcode:
 MyForm := TMyForm.Create;
 try
   MyForm.Showmodal;
 finally
   MyForm.Free;
 end;
Selbst so simpler Code schließt nicht mehr das Fester, weil komischerweise die Referent nach einem Create nicht 1 ist.
Spätestens das dieser Stelle muss also ein Disposeof her.

Also folgende Procedure geschrieben...

Delphi-Quellcode:
Procedure ArcFree(Var Obj);
{$IF not Defined(AUTOREFCOUNT)}
var
   Temp: TObject;
begin
   Temp := TObject(Obj);
   Pointer(Obj) := nil;
   Temp.Free;
end;
{$ELSE}
begin
   if Pointer(Obj) <> NIL then
     begin
       TFMXObject(Obj).Release;
       TFMXObject(Obj).DisposeOf;
     end;

   TObject(Obj) := nil;
end;
{$ENDIF}
ARC hat sicherlich seine Vorteile, aber eigentlich nur, in Hinblick auf die CrossPlattform Programmierung, wenn uns ARC
@EMBT - BITTE PER COMPILER-SCHALTER!!!
auch unter Windows zur Verfügung steht.

Jetzt habe ich eine [Weak] Referenz und speichere diese an 10000 Stellen in Listen usw.
Wenn dann dieses Object geFreeed wird, müssen alle Pointer aus der Liste auf NIL gesetzt werden.

Warum den nicht so arbeiten wir früher und immer ein ArcFree aufrufen?
Keine Weak-Liste die Speicher verbraucht, keine Performance Einbußen bei einem Free, Fester gehen wirklich zu und mein Code läuft auch ohne ARC-Überlegungen.

Ich rede hier nicht von neuem Code...!8-)

Wenn man etwas neu programmiert, kann man sicherlich die Unterschiede - mal eben :wall: - berücksichtigen.

Grüsse und einen schönen 2. Weihnachtsfeiertag

wünscht Mavarik

Sir Rufo 26. Dez 2014 14:01

AW: Weak Referenzen überlegungen...
 
Also der Code
Delphi-Quellcode:
 MyForm := TMyForm.Create;
 try
   MyForm.Showmodal;
 finally
   MyForm.Free;
 end;
funktioniert unter ARC genauso wie unter Nicht-ARC. Der einzige Unterschied ist, dass die Form-Instanz unter ARC noch da ist. Macht aber erstmal nix, denn geschlossen wurde die, denn
Delphi-Quellcode:
ShowModal
kehrt erst dann zurück, wenn die Form geschlossen wurde.

(Ich lasse jetzt mal ausser Acht, dass ARC nur auf den Mobile-Plattformen läuft und dort dieser Code gar nicht funktioniert, weil es dort kein blockierendes
Delphi-Quellcode:
ShowModal
gibt.)

Nehmen wir also mal an, der Code ist so vorhanden:
Delphi-Quellcode:
procedure Foo;
var
  MyForm : TMyForm;
begin
 MyForm := TMyForm.Create;
 try
   MyForm.Showmodal;
 finally
   MyForm.Free;
 end;
end;
dann ist das Verhalten exakt gleich. Nach dem Verlassen der Prozedur/Methode ist die erzeugte Form-Instanz aus dem Speicher verschwunden.
Delphi-Quellcode:
TFoo = class
private
  MyForm : TMyForm;
public
  procedure ShowForm;
end;

procedure TFoo.ShowForm;
begin
 MyForm := TMyForm.Create;
 try
   MyForm.Showmodal;
 finally
   MyForm.Free;
 end;
end;
Und jetzt? Wiederum eine identische Aussenwirkung. Eine neue Form-Instanz wird erzeugt, angezeigt und nach dem Schliessen wird die Methode verlassen. Einziger Unterschied auf ARC bleibt die Instanz bis zum erneuten Aufruf der Methode noch im Speicher.

Was kann man dagegen unternehmen?
Delphi-Quellcode:
procedure TFoo.ShowForm;
begin
 MyForm := TMyForm.Create;
 try
   MyForm.Showmodal;
 finally
   FreeAndNil( MyForm.Free );
 end;
end;
Und nun die Preisfrage: Warum ist die Verwendung von
Delphi-Quellcode:
FreeAndNil
selbst unter Nicht-ARC ratsam?

Logisch: Ich zerstöre die Instanz aber hinterlasse einen ungültigen Referenz-Zeiger in
Delphi-Quellcode:
MyForm
. Wer das tatsächlich so gemacht hat, hat schon immer eine Gratwanderung betrieben.

Bei lokalen Variablen ist das wie gezeigt kein Problem, aber bei nicht lokalen Variablen war der Code schon immer grenzwertig. Auch wenn er sich nicht negativ ausgewirkt hat heisst es nicht, dass es korrekt ist.

Fazit: Bei einer korrekten und robusten Programmierung ist dieser gezeigte Fall absolut kein Problem ;)

Der schöne Günther 26. Dez 2014 14:42

AW: Weak Referenzen überlegungen...
 
Zitat:

Zitat von Mavarik (Beitrag 1284717)
Vor ARC haben wir uns keine sorgen gemacht, oder?

Eigentlich mache ich mir Sorgen, BIS ich ARC auf Windows endlich rundum habe, und nicht nur bei Records, Interfaces und Arrays :wink:

Daniel 26. Dez 2014 16:22

AW: Weak Referenzen überlegungen...
 
"ShowModal" ist wie bereits gesagt kein besonders gutes Beispiel, weil unter iOS zwar unterstützt wird und dort tatsächlich auch blockiert, aber spätestens unter Android ist damit Schluss.
Zudem kann ich den Fehler, dass das Form nicht geschlossen wird, ebenfalls nicht nachstellen - zumindest nicht mit mit o.g. Code.

Hast Du ein echtes Beispiel für uns, wo Dich ARC zwickt?
Über ARC unter Win32 würde ich - Stand heute - nicht nachdenken. Es liegen keine belastbaren Infos vor, dass wir das in endlicher Zeit bekommen würden, vor der Art der Implementation ganz zu schweigen. Das ist reine Spekulation.

Sir Rufo 26. Dez 2014 16:30

AW: Weak Referenzen überlegungen...
 
Die Art der Implementation von ARC ist keine Spekulation, sondern aktuell genau so implementiert ;)

Daniel 26. Dez 2014 16:48

AW: Weak Referenzen überlegungen...
 
Ich meine die Überlegung, ob ARC unter Win32/Win64 - wenn es denn kommt - via Compiler-Schalter steuerbar sein könnte etc.

//edit:

Zum Thema: Eigene Verrenkungen mit .DisposeOf() kann man sich sparen, wenn man das Event OnClose des betreffenden Forms ausprogrammiert und dort den Parameter "Action" auf TCloseAction.caFree setzt. Dann wird der Destruktor auch ARC-konform am Ende aufgerufen.

Mavarik 26. Dez 2014 16:56

AW: Weak Referenzen überlegungen...
 
Sorry sollte natürlich Show und nicht showmodal sein

Sir Rufo 26. Dez 2014 17:14

AW: Weak Referenzen überlegungen...
 
Zitat:

Zitat von Mavarik (Beitrag 1284742)
Sorry sollte natürlich Show und nicht showmodal sein

Das ändert an meiner Aussage nichts. Mit einer lokalen Variablen ist bei beiden Schluss und mit einer nicht-lokalen ist das Design falsch, denn dann ist
Delphi-Quellcode:
FreeAndNil
Pflicht. ;)

Mavarik 26. Dez 2014 21:51

AW: Weak Referenzen überlegungen...
 
Zitat:

Zitat von Sir Rufo (Beitrag 1284743)
Das ändert an meiner Aussage nichts. Mit einer lokalen Variablen ist bei beiden Schluss und mit einer nicht-lokalen ist das Design falsch, denn dann ist
Delphi-Quellcode:
FreeAndNil
Pflicht. ;)

FreeandNIL hilft auch nicht.

Wenn man ein Fenster öffnet, nutzt man i.d.R. doch die Variable im Form.

Aber das war ja nicht die Frage...

Sir Rufo 26. Dez 2014 22:09

AW: Weak Referenzen überlegungen...
 
Zitat:

Zitat von Mavarik (Beitrag 1284757)
Zitat:

Zitat von Sir Rufo (Beitrag 1284743)
Das ändert an meiner Aussage nichts. Mit einer lokalen Variablen ist bei beiden Schluss und mit einer nicht-lokalen ist das Design falsch, denn dann ist
Delphi-Quellcode:
FreeAndNil
Pflicht. ;)

FreeandNIL hilft auch nicht.

Wenn man ein Fenster öffnet, nutzt man i.d.R. doch die Variable im Form.

Aber das war ja nicht die Frage...

Welche "Variable im Form"?

idR heisst ja nicht, dass es korrekt ist. Korrekt ist auf jeden Fall, dass Variablen (vor allem die für Instanz-Referenzen) die nicht lokal sind niemals auf einem ungültigen Wert stehen zu lassen. Selbst unter Nicht-ARC ist das schon immer der direkte Weg zu "Torte-Im-Auge" gewesen.

Ein
Delphi-Quellcode:
FSomeThing.Free
knallt und ist auch mit
Delphi-Quellcode:
if Assigned( FSomeThing ) then
nicht zu bändigen, wenn sich dort noch eine ungültige Referenz befindet. Lösen kann man das nur mit dem Setzen der Variablen auf
Delphi-Quellcode:
nil
und dafür wurde ja extra
Delphi-Quellcode:
FreeAndNil
eingeführt. Und das ist dann auch ARC-Safe.

Mavarik 26. Dez 2014 22:29

AW: Weak Referenzen überlegungen...
 
Zitat:

Zitat von Sir Rufo (Beitrag 1284759)
Welche "Variable im Form"?

idR heisst ja nicht, dass es korrekt ist. Korrekt ist auf jeden Fall, dass Variablen (vor allem die für Instanz-Referenzen) die nicht lokal sind niemals auf einem ungültigen Wert stehen zu lassen. Selbst unter Nicht-ARC ist das schon immer der direkte Weg zu "Torte-Im-Auge" gewesen.

Ein
Delphi-Quellcode:
FSomeThing.Free
knallt und ist auch mit
Delphi-Quellcode:
if Assigned( FSomeThing ) then
nicht zu bändigen, wenn sich dort noch eine ungültige Referenz befindet. Lösen kann man das nur mit dem Setzen der Variablen auf
Delphi-Quellcode:
nil
und dafür wurde ja extra
Delphi-Quellcode:
FreeAndNil
eingeführt. Und das ist dann auch ARC-Safe.

OK - auch wenn das nicht die Frage war:

Eine lokale Variable geht i.d.R. gar nicht... Weil auf dem mobilen Gerät gibt es kein showmodal.

Aber es gibt einen Button oder ein ListElement oder was auch immer...

Darin steht:

MyForm := TMyForm.Create(Application);

Und MyForm ist aus der UMyForm.pas (Die Variable die automatisch definiert wird, wenn du ein neues Form an legst.

MyForm hat auch einen Button

In diesem Buttonclick steht.

Delphi-Quellcode:
MyForm2 := TMyForm2.Create(Application);
MyForm2.KillOldForm(Self);
Wenn Du jetzt in der KillOldForm ein FreeAndNIL aufrufst passiert überhaupt nix...
Da refcount 4 oder großer ist.

Mavarik

Sir Rufo 27. Dez 2014 09:06

AW: Weak Referenzen überlegungen...
 
Das ist eine besondere Situation, da du beim Erzeugen das Lifetime-Management bewusst an eine andere Instanz übergibst. In diesem Fall musst du System.TObject.DisposeOf verwenden.

Mavarik 27. Dez 2014 12:57

AW: Weak Referenzen überlegungen...
 
Zitat:

Zitat von Sir Rufo (Beitrag 1284770)
Das ist eine besondere Situation.

Siehst Du... Obwohl ich davon aus gehe, dass für eine App die mehr als eine - ich nenne das gerne - Klichmich.App ist das nicht besonders, sondern normal ist.

- Es gibt kein Showmodal
- Alle Fenster sind Maximized

Wenn Du also ein sinnvolles UI bauen willst hast Du mehr als 1 Form mit 2 Slide-ins
- Startmenue
- 1..n Programmteile
- Einstellungen
- Stammdaten
- Adresseingaben oder andere Daten

Du willst zwischen den Fenstern hin und her schalten können. Aber natürlich nicht alle Fenster permanent im Speicher halten.

Mavarik

RWarnecke 27. Dez 2014 13:12

AW: Weak Referenzen überlegungen...
 
Zitat:

Zitat von Mavarik (Beitrag 1284785)
Wenn Du also ein sinnvolles UI bauen willst hast Du mehr als 1 Form mit 2 Slide-ins
- Startmenue
- 1..n Programmteile
- Einstellungen
- Stammdaten
- Adresseingaben oder andere Daten

Du willst zwischen den Fenstern hin und her schalten können. Aber natürlich nicht alle Fenster permanent im Speicher halten.

Bei so einer Aufgabenstellung habe ich dann lieber einen TabController genommen, auch gerne mal verschachtelt. Dabei hatte ich dann keine Sorgen mit dem freigeben von Fenstern. Einzigster Nachteil dabei ist, das ab einer bestimmten Anzahl von Tabs das ganze etwas unübersichtlich wird. Das gebe ich gerne zu. Aber mit dem TabController habe ich dann auch ein paar Slides hinbekommen, was mir mit Fenstern nie so richtig gelungen ist.

Sir Rufo 27. Dez 2014 15:01

AW: Weak Referenzen überlegungen...
 
Wir driften vom Thema ab, aber das Konzept bei einer Mobil-App ist wohl durchaus eher eine MainForm mit einem TabControl, wo die einzelnen TabItems eigene Ableitungen von
Delphi-Quellcode:
TTabItem
sind, die dann ein spezielle Ableitung einer
Delphi-Quellcode:
TForm
in sich darstellen (und zwar wird von der Form-Instanz ein
Delphi-Quellcode:
TLayout
der Parent auf das TabItem gelegt).

Ein Frame wäre auch möglich, aber dann kann man zur Design-Time nicht zwischen den Target-Platformen umschalten und spezielle Layouts vorgeben.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:23 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