Autor Beitrag
MKehrer
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

NT, 2000
D6
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

NT, 2000
D6
BeitragVerfasst: Mo 17.03.03 12:02 
Vielleicht noch zur genaueren Darstellung:

ausblenden 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
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

NT, 2000
D6
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

NT, 2000
D6
BeitragVerfasst: 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

ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

NT, 2000
D6
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 896

Win XP, Suse 8.1
Delphi 4/7/8 alles prof
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

NT, 2000
D6
BeitragVerfasst: Mi 19.03.03 11:50 
Das ist es leider nicht, trotzdem Danke
Popov
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: 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

ausblenden Quelltext
1:
If (Y<>FOrigin.Y) then					


aber das hier

ausblenden 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,

ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

NT, 2000
D6
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: 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

ausblenden Quelltext
1:
(Y-FOrigin.Y)					


oder

ausblenden Quelltext
1:
dx/(Y-FOrigin.Y)					


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:

ausblenden Quelltext
1:
dx/(Y-FOrigin.Y)					


oder machst du das in zwei Schritten. Ein mal

ausblenden Quelltext
1:
(Y-FOrigin.Y)					


und dann das

ausblenden Quelltext
1:
dx/0					

_________________
Popov
MKehrer Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 114

NT, 2000
D6
BeitragVerfasst: 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
ausblenden Quelltext
1:
dx/(Y-FOrigin.Y)					

mit der Bedingung Y=FOrigin.Y

dann schaue ich mir den ASM-Code (ctrl-alt-C) und den FPU-Stack (ctrl-alt-F) an.