| Autor |
Beitrag |
MKehrer
      
Beiträge: 114
NT, 2000
D6
|
Verfasst: Mo 17.03.03 11:42
Hi Delphianer,
ich habe ein 'Divide by Zero', das bei mir weder in der Entwicklungsumgebung, noch bei direktem Start der EXE eine Exception auslöst.
Dafür krachts aber bei einem Anwender auf einem anderen Rechner beim Start der EXE ohne Entwicklungsumgebung.
Es kommt halt schon man vor, dass man ein 'Div by Zero' codiert.
Dumm ist´s nur wenn die Entwicklungsumgebung nichts merkt.
Änderungen an den Debug-Options ('Exception to Ignore') bringt nichts.
Die Einstellung 'Float Divide by Zero' ist bei mir auf 'user program; run unhandled'
Weiß jemand wie man das löst?
Manfred
Zuletzt bearbeitet von MKehrer am Mi 19.03.03 10:38, insgesamt 2-mal bearbeitet
|
|
MKehrer 
      
Beiträge: 114
NT, 2000
D6
|
Verfasst: Mo 17.03.03 12:02
Vielleicht noch zur genaueren Darstellung:
Quelltext 1:
| If dx/(Y-FOrigin.Y)<=0 then ..... |
Im Debugger wird folgendes evaluiert:
dx=1
Y=25
FOrigin.Y=25
dx/(Y-FOrigin.Y) = +INF
und wie gesagt keine Exception
Ich hab Delphi 6 Enterprise
???
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Mo 17.03.03 12:34
Die Frage ist ob Y oder FOrigin.Y zu der Zeit 25 oder in Wirklichkeit z.B. 25,000003500 ist. Ich hab schon bei 2 / 2 mal 1,00035 rausgehabt. Was für ein Variablentyp genau ist Y und FOrigin.Y?
_________________ Popov
|
|
MKehrer 
      
Beiträge: 114
NT, 2000
D6
|
Verfasst: Mo 17.03.03 13:39
Titel: Es sind Integers
Hi popov,
so sieht man sich wieder,
ich hoffe Du warst wegen meiner letzten Aufforderung nicht gekränkt.
Aber rückscrollen und nachlesen gehört halt mal dazu, wenn man sich im Kreis dreht.
Zu Deiner Frage:
nun dx, Y und FOrigin.Y sind Integer
(hätte ich vielleicht dazuschreiben sollen)
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Mo 17.03.03 14:00
Titel: Re: Es sind Integers
| MKehrer hat folgendes geschrieben: | | ich hoffe Du warst wegen meiner letzten Aufforderung nicht gekränkt. |
Ich bin nie gekränkt
Ist noch keine Lösung auf dein Problem, aber trotz der Integer ist das Ergebnis Real (wegen a / b und nicht a div b). Bei den angegebenen Werten ist ist das Ergebnis natürlich Null (0), da es aber Real ist, kann die 0 auf deinem Rechner auch 0,000000001 sein. Vielleicht liegt der Fehler da.
Wenn das Ergebnis nicht unbedingt eine Realzahl sein muß, dann kannst du mit Trunc es zum Integer machen oder direkt mit div dividieren.
Vielleicht weiß jemand anders besser wieso auf dem einem Rechner Null rauskommt und auf dem anderen eine sehr kleine Zahl.
_________________ Popov
|
|
MKehrer 
      
Beiträge: 114
NT, 2000
D6
|
Verfasst: Mo 17.03.03 14:20
Hi Popov
Der ausgewertete Term mit Nulldivision wird im Debuger als '+INF' dargestellt
Wenn der Divisor nicht exakt Null ist, müßte entweder
der Term als eine sehr große Zahl evaluiert werden oder
ein Overflow Exception ausgegeben werden.
Außerdem:
Bei folgendem Code ist alles OK
Quelltext 1: 2:
| If (Y<>FOrigin.Y) then If dx/(Y-FOrigin.Y) then .... |
Also folgere ich, dass Y-FOrigin.Y exakt Null ist.
Um´s noch mal klar zu sagen. Die Nulldivision nicht abzufangen ist natürlich ein Entwicklungsfehler, aber ab und zu passierts doch und dies sollte die Entwicklungsumgebung eigentlich merken.
|
|
MKehrer 
      
Beiträge: 114
NT, 2000
D6
|
Verfasst: Mi 19.03.03 10:26
Titel: Jetzt für Leute, die sich in Assembler besser auskennen als
Jetzt für Leute, die sich in Assembler besser auskennen als ich.
Nach genauerer Untersuchung kann ich noch folgendes sagen
Bei dem Code, der die Exception nicht auslöst, ist vor dem Divide Befehl (Assembler: fdivp)
die ZM (Zero Divide Exception Mask) der Control Flags auf 1 gesetzt.
Nach dem fdivp steht im FPU-Register ST0: Spec. INF und die Exception wird übergangen.
Wenn ich im Debugger vor dem fdivp die ZM auf 0 setze, wird die Exception ausgelöst (so soll es auch sein).
Wer setzt denn diese ZM?
Weiterhin ist noch folgendes interressant:
Ich habe den Code, der die Excption übergeht auf 12 anderen Rechnern laufen lassen mit dem Ergebnis
Bei 7 Rechnern (mit Pentium-Processor, darunter auch mein Entwicklungsrechner) wird die Exception übergangen
Bei 5 Rechnern (mit AMD-Processor) wird die Exception ausgelöst.
Langsam glaube ich, dass da der Compiler (D6.0) nicht richtig arbeitet.
Kann mir jemand diese Rätsel erklären?
Manfred
|
|
maximus
      
Beiträge: 896
Win XP, Suse 8.1
Delphi 4/7/8 alles prof
|
Verfasst: Mi 19.03.03 11:39
Hallo. Ich hab es nicht getestet, aber möglicherweise kann man diese verhalten in den projekt-optionen->compiler->*PentiumSave FDIV* an und ausstellen!?
Kannst ja mal testen.
bis denn maximus.
|
|
MKehrer 
      
Beiträge: 114
NT, 2000
D6
|
Verfasst: Mi 19.03.03 11:50
Das ist es leider nicht, trotzdem Danke
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Mi 19.03.03 13:27
Die Lösung glaube ich dir zumindest im Ansatz gegeben zu haben. Mag sein, daß hier noch alles ok ist
Quelltext 1:
| If (Y<>FOrigin.Y) then |
aber das hier
Quelltext 1:
| ... dx/(Y-FOrigin.Y) ... |
kann trotz zwei gleicher Zahlen dennoch zwei mal zwei unterschiedliche Werte ergeben. Ich hab dein DivByZero Problem zwar noch nie gehabt, aber was ich gehabt habe war, daß 2 / 2 schon mal 1.000003500 ausgegeben hat. Diese Fehler passieren, weil hier nie mit der ganze Zahl gerechnet wird. Die Zahlen werden beschnitten, so das sie z.B. in ihre 6 Byte passen. Da gibts einfach Rundungsfehler. Am schlimmsten soll die Zahl vom Typ Real sein. Ich habe sie früher verwendet, aber irgendwann stellte ich fest, daß sie von den Reelen Zahlen an ungenausten ist. Deshalb arbeite ich jetzt immer mit Single, Double oder Extended. Bei dem Real Typ kamm einfach zu oft vor, daß bei einem glattem Ergebnis Nachkommastellen kammen.
Bevor hier weiter gemacht wird solltest du erst beantworten was das Ergebnis bei der Rechning sein soll: dx/(Y-FOrigin.Y). Soll hier ein Integer oder Reele Zahl rauskommen? Wenn Integer, dann teile einfach mit div und dein Problem ist gelöst. Wenn Reele Zahl (also mit Nachkomma), dann mach die Berechnung vorher in einer Single Zahl oder Extended. Geh dann mit dem Ergebnis in die Abfrage.
Glaub mir,
Quelltext 1:
| If (Y<>FOrigin.Y) then |
hat nichts zu sagen. Hier sind die Zahlen noch gleich. Erst nach der Division wird die Zahl ungleich.
Wie gesagt, ich glaube nicht, daß es ein DivByZero Problem ist, sondern ein Berechnungsproblem mit Ungenauigkeit der Nachkommastellen ist.
_________________ Popov
|
|
MKehrer 
      
Beiträge: 114
NT, 2000
D6
|
Verfasst: Mi 19.03.03 13:58
Hi Popov,
| Zitat: | | Die Lösung glaube ich dir zumindest im Ansatz gegeben zu haben |
Da muß ich Dir leider wieder sagen, wenn Du mein Postings richtig lesen würdest, kommst Du drauf, das es das nicht ist.
also das Problem ist ja eigentlich gelöst mit
If (Y<>FOrigin.Y) then ...
Der Klammerausdruck (Y-FOrigin.Y) wird mit exact 0 berechnet und wird im FPU-Stack vor der Division mit "zero" angezeigt, und "zero" in ASM ist halt mal 0 und nicht 1e-8.
Mich nervt ja nur, dass die ZeroDivideMask halt zufällig vor der fdivp auf 1 steht und damit die Exception übergangen wird.
Manfred
|
|
Popov
      
Beiträge: 1655
Erhaltene Danke: 13
WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
|
Verfasst: Mi 19.03.03 15:06
Das ist mehr oder weniger das auf was ich die ganze Zeit hinaus will. Ich versuche dich auch die ganze Zeit auf den kleinen Fehler hinzuweisen.
Ich weiß nicht auch nicht wieso hin und wieder bei 2 / 2 Fehler rauskommen. Schon garnicht kann ich es nachstellen wenn ich es brauche, aber sie sind hin und wieder da. Das nächste mal merke ich mir den Code.
Deshalb glaube ich auch dir, daß das alles so wie du geschreiben hast auch stimmt. Aber ist stelle dir jetzt die Frage: Hast du bei denen Beobachtungen nier eine Null gehabt
Quelltext
oder
Quelltext
Y und FOrigin.Y sind zwei Integer. Was soll da anderes rauskommen als einen Null. Aber dx/(Y-FOrigin.Y) ist eine Fließkommaberechnung. dx div (Y-FOrigin.Y) ist eine Integerberechnung.
Es kann aber auch sein, daß du das die ganze Zeit auch so meinst.
Bevor du also noch mal sagst, daß du eigentlich wqs anderes meinst - das habe ich verstanden. Aber manchmal muß man ein Schritt zurücktreten unm etwas zu sehen.
Ich weiß immer noch nicht wie du den Assemblercode prüfst. Prüfst du was rauskommt wenn du das berechnest:
Quelltext
oder machst du das in zwei Schritten. Ein mal
Quelltext
und dann das
Quelltext
_________________ Popov
|
|
MKehrer 
      
Beiträge: 114
NT, 2000
D6
|
Verfasst: Mi 19.03.03 15:13
| Popov hat folgendes geschrieben: | | Ich weiß immer noch nicht wie du den Assemblercode prüfst. |
Ich mache einen Halte punkt bei
Quelltext
mit der Bedingung Y=FOrigin.Y
dann schaue ich mir den ASM-Code (ctrl-alt-C) und den FPU-Stack (ctrl-alt-F) an.
|
|