Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Initialisierung von result wird wegoptimiert (https://www.delphipraxis.net/193783-initialisierung-von-result-wird-wegoptimiert.html)

bcvs 8. Sep 2017 11:13

Initialisierung von result wird wegoptimiert
 
Hallo zusammen,

ich verwende folgendes Konstrukt:

Delphi-Quellcode:
function irgendwas:boolean;
begin
  result:=false; // diese Zeile wird wegoptimiert
  MyObject:=TMyObject.Create;
  try
    MachwasMit(MyObject);
    result:=true;
  finally
    MyObject.Free;
  end;
end;
Result soll erstmal false sein, und nur wenn in MachwasMit(MyObject) keine Exception aufgetreten ist, auf true gesetzt werden.
Das
Delphi-Quellcode:
result:=false
wird aber wegoptimiert und ich bekomme für diese Zeile die Compilerwarnung
H2007 Auf <Name der Function> zugewiesener Wert wird niemals benutzt.
Bei einer Exception wäre also result undefiniert.

Wenn ich aber eine Hilfsvariable einführe, compiliert es so, wie ich mir das vorstelle, und ich bekomme auch keine Compilerwarnung.

Delphi-Quellcode:
function irgendwas:boolean;
var ok:boolean;
begin
  ok:=false;
  MyObject:=TMyObject.Create;
  try
    MachwasMit(MyObject);
    ok:=true;
  finally
    result:=ok;
    MyObject.Free;
  end;
end;
Wenn ich hier das ok:=false weglasse, bekomme ich sogar richtigerweise die Compilerwarnung
Variable OK ist möglicherweise nicht initialisiert worden.

Wieso erkennt der Compiler bei der Verwendung der Hilfsvariablen, dass diese im try - finally - Block möglicherweise nicht initialisiert wird, bei Verwendung von result jedoch nicht?

D2007

Uwe Raabe 8. Sep 2017 11:30

AW: Initialisierung von result wird wegoptimiert
 
Da die Exception durch das finally ja nicht abgefangen wird gelangt der Result-Wert auch nicht zum Aufrufer zurück. Insofern wird bei einer Exception der Result-Wert auch nie benutzt.

Redeemer 8. Sep 2017 11:39

AW: Initialisierung von result wird wegoptimiert
 
Anders ausgedrückt: Wenn MachWasMit erfolgreich ist, bekommst du True zurück. Wenn MachWasMit fehlschlägt, bricht irgendwas ab. Die Methode gibt also immer True zurück oder schlägt fehl.

himitsu 8. Sep 2017 12:22

AW: Initialisierung von result wird wegoptimiert
 
Beim Zweiten wird es nicht wegoptimiert, da immer im Finally auf diese Variable zugegriffen wird.
Wenn es nicht knallt, dann der Wert von der Zuweisung im Try und wennes vorher knallte, dann die Initialzuweisung.

Bei Zweitem muß die Initialisierung sogar vorhanden sein, da Finally das verwenden könnte (wenn es knall), auch wenn das Result danach wieder weggeworfen wird.
Und beim ersten Beispiel, wird die initialisierung nie verendet (wenn es knallt, dann raucht es ab und keiner brauch das, und wenn es durchlief, dann wird immer nur das Letzte verwendet).

hoika 9. Sep 2017 08:23

AW: Initialisierung von result wird wegoptimiert
 
Hallo,

Zitat:

Bei einer Exception wäre also result undefiniert.
Genau, warum machst du es dann nicht so.

Delphi-Quellcode:
function irgendwas:boolean;
begin
  Result:= False; // diese Zeile wird nicht mehr wegoptimiert

  try
    MyObject:=TMyObject.Create;
    try
      MachwasMit(MyObject);
      Result:= True;
    finally
      MyObject.Free;
    end;
  except
    // nu kommst du
  end;
end;
Übrigens ist es keine Compilerwarnung, sondern ein Hinweis.

idefix2 9. Sep 2017 13:55

AW: Initialisierung von result wird wegoptimiert
 
Ich finde das Schachteln von zwei Try Blöcken in so einem Fall sehr unschön, und auch unnötig.
Try ... except ... end - und gleich danach ein free. Wenn man im Except Block keine Bocksprünge treibt, die ihrerseits wieder zu einer Exception führen können (und das sollte man ohnedies tunlichst vermeiden), wird auf diese Art das free auch ohne zweiten try-Block zuverlässig ausgeführt.

hoika 9. Sep 2017 15:21

AW: Initialisierung von result wird wegoptimiert
 
Hallo,
Einspruch Euer Ehren ;)

Delphi-Quellcode:
procedure MachwasMit(AObject: TMyObject);
begin
  AObject.Free;
end;

function irgendwas:boolean;
begin
  Result:= False; // diese Zeile wird nicht mehr wegoptimiert

  MyObject:=TMyObject.Create;
  try
    MachwasMit(MyObject); // hier wird das Objekt aus Versehen freigegeben
    Result:= True;
  except
    // nu kommst du
  end;

  MyObject.Free; // was passiert dann wohl hier?

end;
Das ist mir auch schon vorgekommen ...
Das leere
except
end;

sollte man natürlich mit einer sinnvollen Meldung (z.B. Logging) füllen.

Uwe Raabe 9. Sep 2017 15:25

AW: Initialisierung von result wird wegoptimiert
 
Zitat:

Zitat von idefix2 (Beitrag 1380689)
Ich finde das Schachteln von zwei Try Blöcken in so einem Fall sehr unschön, und auch unnötig.
Try ... except ... end - und gleich danach ein free. Wenn man im Except Block keine Bocksprünge treibt, die ihrerseits wieder zu einer Exception führen können (und das sollte man ohnedies tunlichst vermeiden), wird auf diese Art das free auch ohne zweiten try-Block zuverlässig ausgeführt.

Häufig wird aber im except-Block zwar die Exception behandelt, aber trotzdem ein erneutes raise ausgeführt. In dem Fall würde das Free ohne den finally-Block dann nicht aufgerufen. Es ist einfach guter Stil, wenn man eine Resource über ein try-finally schützt. Die Behandlung bestimmter Exceptions (einen Blanko-Except-Block ohne re-raise würde ich niemals zulassen) ist davon völlig unabhängig.

idefix2 10. Sep 2017 18:57

AW: Initialisierung von result wird wegoptimiert
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1380691)
Häufig wird aber im except-Block zwar die Exception behandelt, aber trotzdem ein erneutes raise ausgeführt. In dem Fall würde das Free ohne den finally-Block dann nicht aufgerufen.

Wenn im Except-Block ein raise ausgeführt wird, geht das so natürlich nicht.

Zitat:

hier wird das Objekt aus Versehen freigegeben
Ich weiß nicht recht, ob man jeden noch exotischen Programmfehler unbedingt mit einem try-Except absichern muss. Für den Benutzer ist es letztlich ziemlich egal, ob er eine System Exception angezeigt bekommt oder eine Exception, die du selbst ge-raised hast. Exception Handling hat meines Erachtens überhaupt nur da einen Sinn, wo man die Fehlerbedingung wirklich auf vernünftige Weise "handeln" kann. Und Programme sollte man so weit wie möglich austesten, um Exceptions zu vermeiden. Letztens ist es doch so, dass man via Exceptions nur die Situationen in den Griff bekommen kann, wo man bestimmte Fehlertypen voraussieht. Ist das nicht der Fall, dann bleibt das Exception Handling reine Kosmetik.

idefix2 10. Sep 2017 19:16

AW: Initialisierung von result wird wegoptimiert
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1380691)
einen Blanko-Except-Block ohne re-raise würde ich niemals zulassen

Im Allgemeinen hast du recht, aber auch da gibt es Ausnahmen, ist mir letztens erst eine untergekommen:
In einem Computerspiel soll auf einen Klick auf Objekte reagiert werden. Um eine zuverlässige Response des Programms auf Mausklicks sicherzustellen, setzt die Onclick Routine nur eine boolean Variable clicked und kehrt sofort zurück, während eine timergesteuerte Routine die Objekte durchgeht und auf die Klicks dann wirklich reagiert. Eine mögliche Reaktion auf so einen Mausklick kann aber sein, das das Objekt als Ganzes gelöscht wird. Wenn der Spieler zweimal rasch hintereinander ein Objekt anklickt, dann kann es in extrem seltenen Fällen passieren, dass unmittelbar nach dem zweiten Start des Onclick die Timer-Routine dazwischen fährt und dem Onclick sein Objekt "unter den Füssen wegzieht", indem es das Objekt löscht. Dann führt clicked:=true (wie jeder andere Zugriffsversuch auf das Objekt) zu einer Exception, die man ganz einfach ignorieren kann, weil einen Klick auf ein Element, das ohnehin schon zum Löschen markiert war, braucht man nicht mehr zu berücksichtigen, und andere Exceptions sind an dieser Stelle absolut unplausibel.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:33 Uhr.
Seite 1 von 2  1 2      

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