2010-04-13 26 views
20

Possible en double:
Best way to detect integer overflow in C/C++Comment vérifier le débordement d'entier dans C?

Il y a (1):

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

et (2):

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

whichs est prefe rred ou y a-t-il un meilleur moyen.

+0

En fait, le double est pas un doublon du tout, il parle de 'unsigned' qui ont bien définis sémantique enveloppants, alors débordant un entier signé est un comportement non défini dans C. –

+2

Il n'y a pas besoin de vérifier à la fois 'sum

Répondre

-5

Vous n'avez qu'à cocher l'un d'entre eux. Si x + y déborde, il sera inférieur à x et y. Par conséquent:

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

devrait suffire.

Le site suivant a un tas de choses à propos de débordement d'entier:

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

Si vous voulez gérer les nombres négatifs, il peut être étendu:

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

Que faire si «y» est négatif? –

+1

L'affiche d'origine a spécifié des entiers non négatifs, mais j'ai ajouté du code pour gérer les nombres négatifs. – clahey

+18

Ceci n'est pas correct - une fois que 'x + y' a débordé, le programme a un comportement indéfini.Vous devez * vérifier * avant d'exécuter réellement l'opération de débordement - comme vous le faites pour la division entière par zéro. – caf

6

Vous pouvez vérifier vraiment seulement pour débordement avec unsigned entiers et arithmétiques:

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

Le comportement de débordement avec des entiers signés n'est pas défini en C, mais sur la plupart des machines vous pouvez utiliser

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

Cela ne fonctionnera pas sur les machines qui utilisent toute sorte de saturant arithmétique

+4

La vérification du dépassement après le fait avec des entiers signés n'est pas correcte. C'est un comportement indéfini, donc les compilateurs optimisent joyeusement les contrôles sans passer un commutateur comme '-fwrapv' pour activer l'habillage signé comme une extension de langage. Ce n'est pas seulement un problème de portabilité entre les architectures. – strcat

+1

Le débordement pour les entiers signés peut également être vérifié. Voir https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow – sbhatla

47

débordement d'entier est le Exemple canonique de "comportement indéfini" en C (notant que les opérations sur les entiers non-signés ne débordent jamais, elles sont définies à wrap-around à la place). Cela signifie qu'une fois que vous avez exécuté x + y, s'il a débordé, vous êtes déjà arrosé. Il est trop tard pour faire des vérifications - votre programme pourrait déjà avoir planté. Pensez-y comme vérifier la division par zéro - si vous attendez après que la division a été exécutée pour vérifier, il est déjà trop tard. Donc, cela implique que la méthode (1) est la seule façon correcte de le faire. Pour max, vous pouvez utiliser INT_MAX de <limits.h>. Si x et/ou y peuvent être négatifs, alors les choses sont plus difficiles - vous devez faire le test de telle sorte que le test lui-même ne puisse pas provoquer de débordement.

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

Si vous êtes aller à downvote, il est considéré courtois de laisser un commentaire expliquant ce que vous ressentez n'est pas utile ou faux. – caf

+0

Btw, pouvez-vous commenter les performances de cette solution par rapport à d'autres solutions alternatives? – Pacerier

+6

Il est peu logique de comparer les performances avec une solution incorrecte. Quelle autre solution correcte aviez-vous en tête? – caf