Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Prüfung auf Assigned(MyObject) true obwohl MyObject nicht initialisiert wurde (https://www.delphipraxis.net/200768-pruefung-auf-assigned-myobject-true-obwohl-myobject-nicht-initialisiert-wurde.html)

freejay 23. Mai 2019 13:26

AW: Prüfung auf Assigned(MyObject) true obwohl MyObject nicht initialisiert wurde
 
Zitat:

Zitat von haentschman (Beitrag 1432949)
Hallöle...8-)

Besser...
Delphi-Quellcode:
procedure TfMain.Button1Click(Sender: TObject);
var
  In_A: string;
  slShow: TStringList;
begin
  In_A := '';

  slShow := TStringList.Create;
  try
    if In_A = '' then
      exit;
     
  finally
    slShow.Free;
  end;
end;

Danke! Da hast Du natürlich recht: So setze ich es jetzt auch in meinen echten Projekten um...

Uwe Raabe 23. Mai 2019 13:26

AW: Prüfung auf Assigned(MyObject) true obwohl MyObject nicht initialisiert wurde
 
Wobei die Initialisierung von In_A streng genommen redundant ist, da strings als managed type automatisch initialisiert wird. Der Lesbarkeit halber würde ich das aber schon so lassen.

Zitat:

Zitat von Bernhard Geyer (Beitrag 1432947)
Sollte es hier nicht eine Compilerwarnung geben?
Die Zeile "slShow := TStringList.Create;" sollte vor dem try stehen.

Nein, das ist durchaus ein gängiges Muster und erst recht vom Compiler nicht zu beanstanden.

Schokohase 23. Mai 2019 13:38

AW: Prüfung auf Assigned(MyObject) true obwohl MyObject nicht initialisiert wurde
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1432951)
Zitat:

Zitat von Bernhard Geyer (Beitrag 1432947)
Sollte es hier nicht eine Compilerwarnung geben?
Die Zeile "slShow := TStringList.Create;" sollte vor dem try stehen.

Nein, das ist durchaus ein gängiges Muster und erst recht vom Compiler nicht zu beanstanden.

Beispiel:
Delphi-Quellcode:
procedure foo;
var
  sl1, sl2: TStringList;
begin
  sl1 := nil;
  sl2 := nil;
  try

    // beliebiger code hier

    sl1 := TStringList.Create;

    // beliebiger code hier

    sl2 := TStringList.Create;

    // beliebiger code hier

  finally
    sl1.Free;
    sl2.Free;
  end;
end;
Wenn an irgendeiner Stelle von "beliebiger code hier" eine Exception geworfen wird, oder mit Exit der Code verlassen werden soll, dann wird der finally-Block ohne Probleme abgearbeitet.

Dennis07 23. Mai 2019 23:18

AW: Prüfung auf Assigned(MyObject) true obwohl MyObject nicht initialisiert wurde
 
Das Problem wird nur sein, dass du dann nicht mehr den ursprünglichen Fehler mittels Exception-Handling abfangen kannst, weil du dann im
Delphi-Quellcode:
finally
-Abschnitt eine Access-Violation bekommst.
Auch geht das so nur bei objekten, die nicht voneinander abhängig sind.

Schokohase 23. Mai 2019 23:49

AW: Prüfung auf Assigned(MyObject) true obwohl MyObject nicht initialisiert wurde
 
Zitat:

Zitat von Dennis07 (Beitrag 1433001)
Das Problem wird nur sein, dass du dann nicht mehr den ursprünglichen Fehler mittels Exception-Handling abfangen kannst, weil du dann im
Delphi-Quellcode:
finally
-Abschnitt eine Access-Violation bekommst.

Probier es aus, so gibt es eben kein Problem und die Exceptions funktionieren wunderbar.

BTW: Du weißt, dass die Methode
Delphi-Quellcode:
Free
auf
Delphi-Quellcode:
nil
prüft bevor diese den Destructor aufruft? Also davon kann es keine AV geben.
Zitat:

Zitat von Dennis07 (Beitrag 1433001)
Auch geht das so nur bei objekten, die nicht voneinander abhängig sind.

Dann muss man eigentlich nur auf die Reihenfolge bei der Freigabe achten (oder darf gar nicht freigeben, wenn man das Lifetime-Management delegiert habe)

freimatz 24. Mai 2019 13:27

AW: Prüfung auf Assigned(MyObject) true obwohl MyObject nicht initialisiert wurde
 
Puh, da ist einiges falsch.

Das Create gehört vor den try.

Dass das obige "sl1.Free;" funktioniert, liegt vielleicht nur daran, dass bei TStringList zufällig nichts schlimmes passiert.
Free ruft Destroy() auf und wenn dort auf Felder zugegriffen wird, dann gibt es zwangsläufig eine Schutzverletzung.
Wenn bei obigem "// beliebiger code hier" eine Exception passiert, dann bleibt sl1 nil

"Dass die Methode Free auf nil prüft" ist auch falsch. FreeAndNil prüft dagegen.

Uwe Raabe 24. Mai 2019 14:39

AW: Prüfung auf Assigned(MyObject) true obwohl MyObject nicht initialisiert wurde
 
Zitat:

Zitat von freimatz (Beitrag 1433057)
"Dass die Methode Free auf nil prüft" ist auch falsch. FreeAndNil prüft dagegen.

Du irrst gewaltig! In beiden Fällen!

Delphi-Quellcode:
procedure TObject.Free;
begin
// under ARC, this method isn't actually called since the compiler translates
// the call to be a mere nil assignment to the instance variable, which then calls _InstClear
{$IFNDEF AUTOREFCOUNT}
  if Self <> nil then
    Destroy;
{$ENDIF}
end;
Delphi-Quellcode:
procedure FreeAndNil(var Obj);
{$IF not Defined(AUTOREFCOUNT)}
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;
{$ELSE}
begin
  TObject(Obj) := nil;
end;
{$ENDIF}

Schokohase 24. Mai 2019 14:45

AW: Prüfung auf Assigned(MyObject) true obwohl MyObject nicht initialisiert wurde
 
Zitat:

Zitat von freimatz (Beitrag 1433057)
Puh, da ist einiges falsch.

Das Create gehört vor den try.

Dass das obige "sl1.Free;" funktioniert, liegt vielleicht nur daran, dass bei TStringList zufällig nichts schlimmes passiert.
Free ruft Destroy() auf und wenn dort auf Felder zugegriffen wird, dann gibt es zwangsläufig eine Schutzverletzung.
Wenn bei obigem "// beliebiger code hier" eine Exception passiert, dann bleibt sl1 nil

"Dass die Methode Free auf nil prüft" ist auch falsch. FreeAndNil prüft dagegen.

Bitte, erst informieren, dann dementieren.

Das Create kann stehen wo will.
Delphi-Quellcode:
var
  f: TObject;
begin
  f := TObject.Create;
  try

  finally
    f.Free;
  end;
end;
oder
Delphi-Quellcode:
var
  f: TObject;
begin
  f := nil;
  try
    f := TObject.Create;

  finally
    f.Free;
  end;
end;
Ist beides gleichwertig. Die zweite Variante macht allerdings nur dann richtig Sinn, wenn man mehrere Instanzen mit einem Resourcen-Schutzblock absichern kann/will.

Das mit dem Free und nil hat Uwe ja schon erklärt.

Manchmal ist Erkenntnis nur einen Klick entfernt und da wundert man sich halt schon manchmal über das was hier an Wissen offenbart wird.

freimatz 25. Mai 2019 12:40

AW: Prüfung auf Assigned(MyObject) true obwohl MyObject nicht initialisiert wurde
 
Dazu gibt es ja zum Glück das Forum.
Asche auf mein Haupt. Tut mir leid. :oops:
Ich war mir so sicher ... War das schon immer so?

Lustig: Habe nach "procedure TObject.Free;" bei mir gesucht und gefunden:
Delphi-Quellcode:
procedure TObject.Free;
begin
  Dispose(PObject(@Self), Done);
end;
Allerdings stand oben drin "Turbo Pascal Version 7.0" :wink:

dummzeuch 25. Mai 2019 16:28

AW: Prüfung auf Assigned(MyObject) true obwohl MyObject nicht initialisiert wurde
 
Zitat:

Zitat von freejay (Beitrag 1432950)
Zitat:

Zitat von haentschman (Beitrag 1432949)

Besser...
Delphi-Quellcode:
procedure TfMain.Button1Click(Sender: TObject);
var
  In_A: string;
  slShow: TStringList;
begin
  In_A := '';

  slShow := TStringList.Create;
  try
    if In_A = '' then
      exit;
     
  finally
    slShow.Free;
  end;
end;

Danke! Da hast Du natürlich recht: So setze ich es jetzt auch in meinen echten Projekten um...

Naja, das ist zwar nicht falsch, erzeugt aber, wenn In_A = '', unnötigerweise die Stringlist, nur um sie dann sofort wieder freizugeben. Bei einer Stringlist ist das noch relativ egal, aber bei komplexeren Klassen kann der Constructor schonmal einiges an Ressource fressen, so dass man sie nur erzeugen sollte, wenn wirklich notwendig. Die Variante mit slShow := nil vor dem Try ist in dem Fall dann besser.


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:02 Uhr.
Seite 2 von 2     12   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz