Also die CPU dann etwas anderes macht, wenn man es versucht.
z.B. den Rechner in eine halt Zustand versetzen oder irgendwas in der
Art?
Die Frage bezieht sich auf diesen Code:
1
int x;
2
...
3
if((x+5)<x)
4
{ /* Handle overflow */ }
5
else
6
{ /* No overflow */ }
Aus diesem Kommentar:
https://www.heise.de/forum/heise-Developer/News-Kommentare/Programmiersprache-Naechste-Version-von-C-in-Arbeit/Man-findet-sicher-mehr-als-genug-folgenden-Code/posting-33418584/show/
Die Aussage, die da drin steckt, dass ein Überlauf prinzipiell
undefiniertes Verhalten ist, ist zwar richtig, aber mir fällt jetzt auch
keine Architektur ein, wo obiges Codebeispiel dann in der Praxis
wirklich zu ein Problem führt, was nicht bedacht ist.
Denn wenn x max int ist, dann dürft eine Addition mit einem weiteren
Wert auf jeder mir bekannten Plattform zu einem Überlauf führen, auch
wenn das ganz klar natürlich rein formal betrachtet aus Sicht der
Sprache undefiniertes Verhalten ist.
Das Problem ist also nur dann eines, wenn es eine Architektur gäbe, in
der ein Überlauf nicht stattfinden kann. Dann hätte man einen Zustand,
der vom Code nicht mehr abgefangen wird.
Anzumerken ist hier, dass der C Standard vorschreibt, dass ein int immer
ein signed int ist.
Bei char ist das anders, da kann es architekturabhängig sein.
Oder meint der Kommentarschreiber etwas anderes?
Nano schrieb:> Die Aussage, die da drin steckt, dass ein Überlauf prinzipiell> undefiniertes Verhalten ist, ist zwar richtig, aber mir fällt jetzt auch> keine Architektur ein, wo obiges Codebeispiel dann in der Praxis> wirklich zu ein Problem führt, was nicht bedacht ist.
Das Problem liegt nicht in der Maschine. Sondern an einem Compiler, der
völlig legal if((x+5)<x) zu if (0) optimiert.
Nun ja, zum Thema gibts hier zillions Threads.
Das Problem hat nichts mit der Architektur zu tun, sondern schlicht
damit daß der C Standard halt einen int overflow per undefined behavior
quasi verbietet.
Oliver
(prx) A. K. schrieb:> Nano schrieb:>> Die Aussage, die da drin steckt, dass ein Überlauf prinzipiell>> undefiniertes Verhalten ist, ist zwar richtig, aber mir fällt jetzt auch>> keine Architektur ein, wo obiges Codebeispiel dann in der Praxis>> wirklich zu ein Problem führt, was nicht bedacht ist.>> Das Problem liegt nicht in der Maschine. Sondern an einem Compiler, der> völlig legal if((x+5)<x) zu if (0) optimiert.
Ah, danke. Ja, das macht dann schon mehr Sinn.
Nano schrieb:> Also die CPU dann etwas anderes macht, wenn man es versucht.> z.B. den Rechner in eine halt Zustand versetzen oder irgendwas in der> Art?
Die MC68000-Familie hat einen TRAPV Befehl und die Arithmetik-Befehle
setzen ggf. das V Flag. Also kann man in Assembler sehr effektiv bei
Overflow eine Exception erzeugen. Standard-C ist eben etwas anderes,
obwohl dem GCC die Idee nicht ganz fremd zu sein scheint:
https://codeforces.com/blog/entry/73183
Was ich mir auch noch vorstellen könnte, ist dass bei einem Overflow mit
Max-Int weitergerechnet wird. Als konservativen Kompromiss, dass bei
einem versehentlichen Overflow die Rakete nicht sofort abstürzt (sondern
vielleicht nur ihre Bahn ändert). Obs das in Realität gibt, egal ob auf
Prozessorebene oder Compilerebene, weiß ich nicht.
Bauform B. schrieb:> Nano schrieb:>> Also die CPU dann etwas anderes macht, wenn man es versucht.>> z.B. den Rechner in eine halt Zustand versetzen oder irgendwas in der>> Art?>> Die MC68000-Familie hat einen TRAPV Befehl und die Arithmetik-Befehle> setzen ggf. das V Flag. Also kann man in Assembler sehr effektiv bei> Overflow eine Exception erzeugen.
Danke.
> Standard-C ist eben etwas anderes,> obwohl dem GCC die Idee nicht ganz fremd zu sein scheint:>> https://codeforces.com/blog/entry/73183
Das ist ja praktisch.
Kann man dem noch irgendeine Fehlermeldung übergeben?
Wenn ich einen overflow erzeuge und diese Compileranweisung in der
Quellcodedatei mit angebe, dann bekomme ich die Meldung "Abgebrochen".
Schöner wäre aber, wenn ich noch eine genauere Fehlermeldung übergeben
könnte.
Maxe schrieb:> Was ich mir auch noch vorstellen könnte, ist dass bei einem Overflow mit> Max-Int weitergerechnet wird.
Nennt sich "saturation arithmetic". Portabel ohne Verlust von normaler
arithmetischer Notation implementierbar in beispielsweise C++. Wer es
eilig hat, kann dafür auf SSE2 und AVX2 zurückgreifen. Da man sowas in
Rechnungen für Grafik und Audio ganz gut brauchen kann, existierte das
bereits in MMX als entsprechende Maschinenbefehle. Bei DSPs ist das
wahrscheinlich auch üblich.
Nano schrieb:> Wenn ich einen overflow erzeuge und diese Compileranweisung in der> Quellcodedatei mit angebe, dann bekomme ich die Meldung "Abgebrochen".> Schöner wäre aber, wenn ich noch eine genauere Fehlermeldung übergeben> könnte.
Vielleicht geht es mit einem signal handler der SIGABRT abfängt. Der
kann die Adresse des Overflows ausgeben. Mit addr2line bekommt man den
Namen der Funktion und die (ungefähre) Zeilennummer.
Maxe schrieb:> Was ich mir auch noch vorstellen könnte, ist dass bei einem Overflow mit> Max-Int weitergerechnet wird. Als konservativen Kompromiss, dass bei> einem versehentlichen Overflow die Rakete nicht sofort abstürzt (sondern> vielleicht nur ihre Bahn ändert). Obs das in Realität gibt, egal ob auf> Prozessorebene oder Compilerebene, weiß ich nicht.
Du kannst beliebige Festlegungen treffen. Helfen tun sie alle nicht.
Pragmatisch wäre es vielleicht, es implementation defined zu machen,
halt das, was es ohne Sonderbehandlung auch tun würde (und in den
meisten fällen ohne Optimierung tut).
Saturierend führt z.B. in die Irre bei "while(y++<=x);" oder bei
"x+999-1000" für große x.
Bauform B. schrieb:> Nano schrieb:>> Wenn ich einen overflow erzeuge und diese Compileranweisung in der>> Quellcodedatei mit angebe, dann bekomme ich die Meldung "Abgebrochen".>> Schöner wäre aber, wenn ich noch eine genauere Fehlermeldung übergeben>> könnte.>> Vielleicht geht es mit einem signal handler der SIGABRT abfängt. Der> kann die Adresse des Overflows ausgeben. Mit addr2line bekommt man den> Namen der Funktion und die (ungefähre) Zeilennummer.
Danke, das hat bestens geklappt.
Nano schrieb:> Also die CPU dann etwas anderes macht, wenn man es versucht.> z.B. den Rechner in eine halt Zustand versetzen oder irgendwas in der> Art?
Ja, MIPS. Dort gibt es die Add und Sub Befehle jeweils in einer signed
und unsigned Variante.
Die Unsigned Variante rechnet einfach im zweier Komplement mit Überlauf.
Die Signed Variante rechnet genauso, löst bei einem Überlauf aber einen
Overflow Interrupt aus.
Und ja - es gibt Compiler, die für signed Integer Berechnungen wirklich
den Befehl mit Overflow Interrupt benutzen. War für mich eine böse
Überraschung vor ein paar Jahren.
Nano schrieb:> Anzumerken ist hier, dass der C Standard vorschreibt, dass ein int immer> ein signed int ist.
Er schreibt aber nichts über die Darstellung vor - Betrag und Vorzeichen
wäre auch möglich. Das ist der Grund, wieso es undefined behaviour ist.
Eigentlich hätte es natürlich implementation defined behaviour sein
müssen, aber das Standard-Komitee ist damals leider mit der Gießkanne
durchgegangen und hat sehr viel als UB definiert, was IB hätte sein
sollen.
Nop schrieb:> Nano schrieb:>>> Anzumerken ist hier, dass der C Standard vorschreibt, dass ein int immer>> ein signed int ist.>> Er schreibt aber nichts über die Darstellung vor - Betrag und Vorzeichen> wäre auch möglich. Das ist der Grund, wieso es undefined behaviour ist.
Woher weißt du, dass genau das der Grund ist?
mh schrieb:> Woher weißt du, dass genau das der Grund ist?
Weil sonst der Compiler für ein portables Überlaufverhalten auf allen
Plattformen extra Code einfügen müßte, und das würde Performance kosten.
Das ist genau dasselbe Problem wie Shiften mit mehr als der
zugrundeliegenden Wortbreite, was aus eben demselben Grund undefined
behaviour ist.
Die "Rationale" sagt dazu:
"The keyword unsigned is something of a misnomer, suggesting as it does
in arithmetic that it is non-negative but capable of overflow. The
semantics of the C type unsigned is that of modulus, or wrap-around,
arithmetic for which overflow has no meaning. The result of an unsigned
arithmetic operation is thus always defined, whereas the result of a
signed operation may be undefined. In practice, on two’s-complement
machines, both types often give the same result for all operators except
division, modulus, right shift, and comparisons. Hence there has been a
lack of sensitivity in the C community to the differences between signed
and unsigned arithmetic."
Bauform B. schrieb:> Die MC68000-Familie hat einen TRAPV Befehl und die Arithmetik-Befehle> setzen ggf. das V Flag. Also kann man in Assembler sehr effektiv bei> Overflow eine Exception erzeugen.
In Assembler schon. In einem C Compiler wäre das komplexer. Denn dessen
Arithmetik findet mindestens als "int" statt, weshalb Rechnungen mit
Datentypen kleiner als "int" erst überlaufen dürfen, wenn sie auf das
Zielformat eingedampft werden. Nicht aber schon in der Rechnung vorher.
Da hilft TRAPV nur in sehr einfach gelagerten Fällen weiter.
Nils schrieb:> Und ja - es gibt Compiler, die für signed Integer Berechnungen wirklich> den Befehl mit Overflow Interrupt benutzen. War für mich eine böse> Überraschung vor ein paar Jahren.
Ich nehme an, dass auf einer solchen Plattform nur int/long bei Überlauf
wegfliegen, nicht aber kleinere Formate.
Speziell bei Signalprozessoren gibt es saturierende Arithmetik. Wenn Du
da irgendwo am Anschlag bist, kommst Du nicht drüber. Ein x=MAXINT; x
++; ergibt dort weiterhin MAXINT. Dieses Verhalten ist bei digitalen
Filtern z.B. sinnvoll.
fchk
Nop schrieb:> mh schrieb:>>> Woher weißt du, dass genau das der Grund ist?>> Weil sonst der Compiler für ein portables Überlaufverhalten auf allen> Plattformen extra Code einfügen müßte, und das würde Performance kosten.> Das ist genau dasselbe Problem wie Shiften mit mehr als der> zugrundeliegenden Wortbreite, was aus eben demselben Grund undefined> behaviour ist.
Auch das ist vermutlich nur eine Vermutung deinerseits. Wäre schön, wenn
du es auch so vormulieren würdest. Es ist eine naheliegende erklärung,
aber du weißt es nicht sicher. Also ein "das ist vermutlich der Grund"
statt "das ist der Grund".
mh schrieb:> Also ein "das ist vermutlich der Grund" statt "das ist der Grund".
Wenn Dennis R. in irgendeinem Interview 30 jahre später irgendwas dazu
gesagt hätte, ... dann wäre es wirklich so? Dann wüssten wir, warum es
seinerzeit so gemacht und nie geändert wurde? Oder welche Art von Beweis
stellst Du Dir vor?
Nop schrieb:> Eigentlich hätte es natürlich implementation defined behaviour sein> müssen
... um bei mancher Implementierung dann auf "unspecified" ausweichen zu
müssen, weil es wie oben beschrieben angesichts der übrigen Regeln von C
nicht immer einfach ist, überhaupt ein konsistentes Verhalten zu
implementieren. Oder was hältst du davon, wenn
int i = INT_MAX;
i += 1;
auf die Nase fällt, weil der "add signed word with overflow exception"
dabei eine Exception auslöst, während dies bei
short i = SHORT_MAX;
i += 1;
mangels Überlauf bei der Addition im Register nicht geschieht?
(prx) A. K. schrieb:> ... um bei mancher Implementierung dann auf "unspecified" ausweichen zu> müssen, weil es wie oben beschrieben angesichts der übrigen Regeln von C> nicht immer einfach ist, überhaupt ein konsistentes Verhalten zu> implementieren.
Insbesondere auch bei Optimierungen. Wenn sich der Compiler auf ein
bestimmtes Verhalten festlegen muss, dann muss dieses auch unabhängig
von jeglicher Optimierung immer gleich sein. Das kann das Potenzial für
Optimierungen deutlich einschränken.
A. S. schrieb:> mh schrieb:>> Also ein "das ist vermutlich der Grund" statt "das ist der Grund".>> Wenn Dennis R. in irgendeinem Interview 30 jahre später irgendwas dazu> gesagt hätte, ... dann wäre es wirklich so? Dann wüssten wir, warum es> seinerzeit so gemacht und nie geändert wurde? Oder welche Art von Beweis> stellst Du Dir vor?
Ich verlange keinen Beweis. Es wäre nur schön wenn Leute nicht behaupten
würden "X ist der Grund", wenn sie nicht wissen, dass es der eine Grund
ist und eigentlich ein "Ich denke X ist der Grund" oder "X ist ein
möglicher Grund" angebracht ist.
Nils schrieb:> Ja, MIPS. Dort gibt es die Add und Sub Befehle jeweils in einer signed> und unsigned Variante.>...> Die Signed Variante rechnet genauso, löst bei einem Überlauf aber einen> Overflow Interrupt aus.>> Und ja - es gibt Compiler, die für signed Integer Berechnungen wirklich> den Befehl mit Overflow Interrupt benutzen. War für mich eine böse> Überraschung vor ein paar Jahren.
Gut zu wissen. Danke.
fchk schrieb:> Speziell bei Signalprozessoren gibt es saturierende Arithmetik. Wenn Du> da irgendwo am Anschlag bist, kommst Du nicht drüber. Ein x=MAXINT; x> ++; ergibt dort weiterhin MAXINT. Dieses Verhalten ist bei digitalen> Filtern z.B. sinnvoll.>> fchk
Danke.
Ein wesentlicher Unterschied zwischen Mensch und Computer ist, dass ein
Mensch mit beliebig, ev. auch unendlich grossen Zahlen rechnen kann, ein
Computer nicht. Ein Mensch denkt sich bei einem arithmetischen Überlauf
einfach noch eine Stelle dazu. Kein Problem, ist nur ev. mühselig
hinzuschreiben.
Man könnte das einem Computer beibringen, wenn man prinzipiell mit big
integern rechnet und diese bei Bedarf verlängert. Aber ich wüsste nicht
welches praktische Problem man damit lösen sollte, bestimmt nicht das
des TO.
Georg
Georg schrieb:> Ein wesentlicher Unterschied zwischen Mensch und Computer ist, dass ein> Mensch mit beliebig, ev. auch unendlich grossen Zahlen rechnen kann, ein> Computer nicht.
Der Mensch kann sich beliebig große Zahlen theoretisch vorstellen, aber
zum praktischen Rechnen braucht er den Computer.
Du kannst ja mal aus Spaß eine AES- oder RSA-Verschlüsselung mit real
eingesetzten Schlüssellängen von Hand durchrechnen. Viel Spaß.
Oliver
Oliver S. schrieb:> Der Mensch kann sich beliebig große Zahlen theoretisch vorstellen, aber> zum praktischen Rechnen braucht er den Computer.
Es wurden schon Planetenbahnen berechnet und tausende Stellen von Pi,
bevor es überhaupt Computer gab.
Vielleicht hast du ja recht für "moderne Menschen".
Georg
Georg schrieb:> Es wurden schon Planetenbahnen berechnet und tausende Stellen von Pi,> bevor es überhaupt Computer gab.
Und Computer haben eindrucksvoll gezeigt, wie ungeeignet Menschen für
das mühselige Abarbeiten von Algorithmen sind.
Georg schrieb:> Es wurden schon Planetenbahnen berechnet und tausende Stellen von Pi,> bevor es überhaupt Computer gab.
Ersteres erfordert keine goßen Zahlen, und zweiteres stimmt schlicht
nicht.
Klaus W. schrieb:> ... und Logarithmentafeln!
7-stellige
Oliver