2010-04-13 12 views
20

Mögliche Duplizieren:
Best way to detect integer overflow in C/C++Wie überprüft man Integerüberlauf in C?

Es gibt (1):

// assume x,y are non-negative 
if(x > max - y) error; 

Und (2):

// assume x,y are non-negative 
int sum = x + y; 
if(sum < x || sum < y) error; 

Rechenblatt prefe ist Oder gibt es einen besseren Weg?

+0

Eigentlich ist das Duplikat überhaupt kein Duplikat, es geht um 'unsigned' spricht die Wraparound Semantik gut definiert hat, während eine ganze Zahl mit Vorzeichen überquell in C. undefiniertes Verhalten ist –

+2

Es gibt keine Notwendigkeit, beide zu überprüfen ist, 'sum

Antwort

-5

Sie müssen nur einen von ihnen überprüfen. Wenn x + y überläuft, ist es kleiner als sowohl x als auch y. Also:

int sum = x + y; 
if (sum < x) error; 

sollte ausreichen.

Die folgende Website hat ein paar Sachen über Integer-Überlauf:

http://www.fefe.de/intof.html

Wenn Sie negative Zahlen behandelt werden sollen, kann es erweitert werden:

int sum = x + y; 
if (y >= 0) { 
    if (sum < x) error; 
} else { 
    if (sum > x) error; 
} 
+1

Was ist, wenn 'y' negativ ist? –

+1

Das ursprüngliche Poster spezifizierte nicht negative ganze Zahlen, aber ich habe Code hinzugefügt, um negative Zahlen zu behandeln. – clahey

+18

Dies ist nicht korrekt - sobald 'x + y' übergelaufen ist, hat das Programm ein undefiniertes Verhalten.Sie * müssen * überprüfen, bevor Sie tatsächlich die Überlaufoperation ausführen - genau wie bei der Ganzzahldivision durch Null. – caf

6

Sie können wirklich nur Scheck für Überlauf mit unsigned ganze Zahlen und arithmatic:

unsigned a,b,c; 
a = b + c; 
if (a < b) { 
    /* overflow */ 
} 

Das Verhalten von Überlauf mit signierten ganzen Zahlen ist in C nicht definiert, aber auf den meisten Maschinen können Sie

int a,b,c; 
a = b + c; 
if (c < 0 ? a > b : a < b) { 
    /* overflow */ 
} 

Diese Arbeit wird nicht auf Maschinen verwenden, das jede Art der Nutzung von

Arithmetik sättigenden
+4

Überprüfung auf Überlauf nach der Tatsache mit vorzeichenbehafteten Ganzzahlen ist nicht korrekt. Es ist undefiniertes Verhalten, so dass Compiler die Überprüfungen glücklicherweise optimieren, ohne einen Schalter wie '-fwrapv' zu übergeben, um das signierte Wrapping als Spracherweiterung zu aktivieren. Es ist nicht nur ein Problem mit der Portabilität von Architekturen. – strcat

+1

Überlauf für vorzeichenbehaftete Ganzzahlen kann auch überprüft werden. Siehe https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Stellen Sie sicher, dass + Operationen + auf + signierten + Integern + nicht + in + Überlauf resultieren + – sbhatla

47

Integer Überlauf das ist ein kanonisches Beispiel für "undefiniertes Verhalten" in C (wobei zu beachten ist, dass Operationen an Ganzzahlen ohne Vorzeichen niemals überlaufen, sie stattdessen als Wrap-Around definiert sind). Dies bedeutet, dass, sobald Sie x + y ausgeführt haben, wenn es übergelaufen ist, Sie bereits abgespritzt sind. Für eine Überprüfung ist es zu spät - Ihr Programm könnte bereits abgestürzt sein. Stellen Sie es sich vor, als ob Sie nach Division durch Null suchen würden - wenn Sie warten, bis die Division ausgeführt wurde, um zu überprüfen, ist es schon zu spät.

Das bedeutet also, dass Methode (1) der einzig richtige Weg ist. Für max können Sie INT_MAX von <limits.h> verwenden.

Wenn x und/oder y negativ sein können, dann sind die Dinge schwieriger - Sie müssen den Test so durchführen, dass der Test selbst keinen Überlauf verursachen kann.

if ((y > 0 && x > INT_MAX - y) || 
    (y < 0 && x < INT_MIN - y)) 
{ 
    /* Oh no, overflow */ 
} 
else 
{ 
    sum = x + y; 
} 
+5

Wenn Sie sind Wenn Sie zu Downvote gehen, wird es als höflich angesehen, einen Kommentar zu hinterlassen, in dem Sie erklären, was Sie für nicht hilfreich oder falsch halten. – caf

+0

Btw, können Sie die Leistung dieser Lösung im Vergleich zu anderen alternativen Lösungen kommentieren? – Pacerier

+6

Es macht wenig Sinn, die Leistung mit einer falschen Lösung zu vergleichen. Welche andere richtige Lösung hatten Sie im Sinn? – caf