Forum: PC-Programmierung Gibt es CPU Architekturen in dem ein signed int nicht überlaufen kann?


von Nano (Gast)


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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.

von Oliver S. (oliverso)


Lesenswert?

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

von Nano (Gast)


Lesenswert?

(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.

von Bauform B. (bauformb)


Lesenswert?

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

von Maxe (Gast)


Lesenswert?

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.

von Nano (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
Beitrag #6873343 wurde vom Autor gelöscht.
von Bauform B. (bauformb)


Lesenswert?

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.

von A. S. (Gast)


Lesenswert?

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.

von Nano (Gast)


Lesenswert?

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.

von Nils (Gast)


Lesenswert?

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.

von Nop (Gast)


Lesenswert?

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.

von mh (Gast)


Lesenswert?

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?

von Nop (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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."

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von fchk (Gast)


Lesenswert?

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

von mh (Gast)


Lesenswert?

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".

von A. S. (Gast)


Lesenswert?

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?

von (prx) A. K. (prx)


Lesenswert?

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?

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Nano schrieb:
> if((x+5)<x)

Dann schreib doch solchen Bullshit einfach nicht hin.
Der Test geht doch regelkonform und besser lesbar so:
1
if(x>(INT_MAX-5))

von Rolf M. (rmagnus)


Lesenswert?

(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.

: Bearbeitet durch User
von mh (Gast)


Lesenswert?

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.

von Nano (Gast)


Lesenswert?

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.

von Nano (Gast)


Lesenswert?

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.

von Georg (Gast)


Lesenswert?

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

von Oliver S. (oliverso)


Lesenswert?

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

von Georg (Gast)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

... und Logarithmentafeln!

von Jemand (Gast)


Lesenswert?

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.

von Oliver S. (oliverso)


Lesenswert?

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

von mh (Gast)


Lesenswert?

An den paar Posts kann man sehen wie schlecht Menschen beim Umgang mit 
"unendlich großen Zahlen" (wie auch immer man das definiert) sind.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.