Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi NaN oder Exception bei Division durch Null (https://www.delphipraxis.net/169046-nan-oder-exception-bei-division-durch-null.html)

Jaynder 26. Jun 2012 10:34

Delphi-Version: 2010

NaN oder Exception bei Division durch Null
 
Hallo, habe auf einmal etwas sehr Merkwürdiges in einem alten Projekt.
Musste jetzt nach Monaten ein paar Dinge ändern, und auf einmal crasht
es an einer Stelle, die früher durchgelaufen ist.

Im Prinzip ist die Situation folgende:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
  var N, M: Double;
begin
  N := 0;
  M := 17 / N; // hier jetzt EZeroDivide, vorher war M=NaN
end;
Bislang war M hinterher NaN und das Programm lief ohne Exception weiter.
Das ungültige Ergebnis wurde später im Programm gefiltert.
Jetzt steigt die Exception und nichts ist wie vorher.

Wie werde ich die Excerption wieder los, will jetzt nicht mein ganzes Programm ändern...

Bummi 26. Jun 2012 10:53

AW: NaN oder Exception bei Division durch Null
 
Über Sinn oder Unsinn kann man sicher streiten ...

http://docwiki.embarcadero.com/CodeS...W_%28Delphi%29

Delphi-Quellcode:
uses math;
procedure TForm5.FormCreate(Sender: TObject);
begin

 SetExceptionMask(GetExceptionMask + [exZeroDivide]);
end;

procedure TForm5.FormDestroy(Sender: TObject);
begin
 SetExceptionMask(GetExceptionMask - [exZeroDivide]);
end;

gammatester 26. Jun 2012 10:58

AW: NaN oder Exception bei Division durch Null
 
Daß Du früher NaN hattest, finde ich sehr merkwürdig! Ich würde +Inf erwarten wie in diesem Beispiel:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  emask: TFPUExceptionMask;
  x,y,z: double;
begin
  emask := GetExceptionMask;
  SetExceptionMask(emask + [exZeroDivide]);
  x := 0;
  y := 17;
  z := y/x;
  ShowMessage(FloatToStr(z));
  SetExceptionMask(emask);
end;
Es zeigt auch wie Du die Exception 'Division durch 0' loswirst. Allerdings: Wenn das nur an einer Stelle relevant ist, solltest Du try / except verwenden. Und global die Exceptions zu maskieren, ist nicht zu empfehlen.

Gruß Gammatester

Jaynder 26. Jun 2012 11:03

AW: NaN oder Exception bei Division durch Null
 
Danke Bummi. Das das Unsinn ist, steht außer Frage, hatte ich auch noch nie verwendet.
Aber vielleicht bekomme damit ich diese alte Projekt wieder zum Laufen...

und gammatester: im habe gerade mal das alte Projekt aus dem SVN ausgecheckt:
es ist tatsächlich nachvollziehbar NaN!! Und mit try except hast du natürlich recht,
aber die Stelle sitzt so tief drinnen, kann ich nicht mal eben schnell ändern.

himitsu 26. Jun 2012 12:18

AW: NaN oder Exception bei Division durch Null
 
Zitat:

Wenn das nur an einer Stelle relevant ist, solltest Du try / except verwenden.
Wozu diese Exception abfangen, nachdem es geknallt hat, wenn man vorher auch einfach auf <>0 prüfen könnte?

Wenn es vorher nicht knallte, dann hatte aber schonml jemand an der ExceptionMask rumgespielt, denn standardmäßig bekommt man die Exceptions.
Eventuell irgendeine Fremdkomponente verwendet, welche netter Weise an globalen Einstellungen rumspielt(e) ?

gammatester 26. Jun 2012 12:55

AW: NaN oder Exception bei Division durch Null
 
Zitat:

Zitat von himitsu (Beitrag 1172476)
Zitat:

Wenn das nur an einer Stelle relevant ist, solltest Du try / except verwenden.
Wozu diese Exception abfangen, nachdem es geknallt hat, wenn man vorher auch einfach auf <>0 prüfen könnte?

Weil es in der Regel ja nicht reicht, auf <> 0 zu testen! Versuch's doch mal mit
Delphi-Quellcode:
var
  x,y,z: double;
begin
  x := 3e-308;
  y := 17;
  z := y/x;
  ShowMessage(FloatToStr(z));
end;
Wobei ich davon ausgehe, daß x bei seinem Aufruf normalerweise nicht 0 oder sehr klein ist, es aber passieren kann. (Wenn x immer 0 ist, wäre es ziemlich unsinnig, die Rechnungen zumachen).

Jaynder 26. Jun 2012 13:21

AW: NaN oder Exception bei Division durch Null
 
So, nun hat sich einiges geklärt, aber nicht alles.

gammatester: du hattes Recht mit +Inf und ich mit -NaN:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
  var N, M: Double;
begin
  N := 0;
  M := 7 / N; // hier jetzt EZeroDivide, vorher M=+Inf
  M := 0 / N; // hier jetzt EZeroDevide, vorher M=-NaN
end;
himitsu: es ist tatsächlich eine Fremdkomponente im Spiel:
der OpenGL-Wrapper GL.pas schaltet die Exceptions im
initialization-Abschnitt mit Set8087CW($133F) knallhart ab.

Die Änderung in meinen Projekt war, das ich die Unit inzwischen
nicht mehr explizit ins Projekt eingebunden habe sondern implizit
über den Bibliothekssuchpfad. Warum deshalb diese Abschaltung nun
nicht mehr greift, ist mir allerdings ein Rätsel.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:06 Uhr.

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