2010-04-13 25 views
20

Duplicar posible:
Best way to detect integer overflow in C/C++¿Cómo verificar el desbordamiento de enteros en C?

No ha (1):

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

Y (2):

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

Quál ea es prefe o hay una mejor manera.

+0

En realidad, el duplicado no es un duplicado en absoluto, que está hablando de 'unsigned' que han bien definidas semántica envolventes, mientras que desborda un entero con signo es un comportamiento indefinido en C. –

+2

No hay necesidad de comprobar tanto 'suma

Respuesta

-5

Solo tiene que marcar una de ellas. Si x + y se desborda, será menor que tanto x como y. Por lo tanto:

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

debería ser suficiente.

El siguiente sitio tiene un montón de cosas sobre el desbordamiento de enteros:

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

Si desea manejar números negativos, que se puede ampliar:

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

¿Qué pasa si 'y' es negativo? –

+1

El cartel original especificaba enteros no negativos, pero he agregado código para manejar números negativos. – clahey

+18

Esto no es correcto: una vez que 'x + y' se ha desbordado, el programa tiene un comportamiento indefinido.Usted * tiene * que verificar antes de ejecutar realmente la operación de desbordamiento, tal como lo hace para la división de enteros por cero. – caf

6

Usted puede realmente único freno para desbordamiento con unsigned enteros y aritmáticos:

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

El comportamiento de desbordamiento de enteros con signo no está definida en C, pero en la mayoría de las máquinas que se pueden utilizar

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

esto no funcionará en máquinas que utilizan cualquier tipo de saturar la aritmética

+4

La comprobación del desbordamiento después del hecho con enteros con signo no es correcta. Es un comportamiento indefinido, por lo que los compiladores optimizarán las comprobaciones sin pasar un interruptor como '-fwrapv' para habilitar el envolvimiento firmado como una extensión de idioma. No es solo un problema de portabilidad en arquitecturas. – strcat

+1

El desbordamiento para enteros con signo también se puede verificar. Ver https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow – sbhatla

47

Desbordamiento de enteros es la Ejemplo canónico de "comportamiento indefinido" en C (teniendo en cuenta que las operaciones en enteros sin signo nunca se desbordan, en su lugar se definen para envolver). Esto significa que una vez que haya ejecutado x + y, si se desbordó, ya está con la manguera. Es muy tarde para hacer una comprobación: su programa ya podría haberse bloqueado. Piense en ello como buscar la división por cero: si espera hasta después de que se haya ejecutado la división para verificar, ya es demasiado tarde.

Esto implica que el método (1) es la única forma correcta de hacerlo. Para max, puede usar INT_MAX desde <limits.h>.

Si x y/o y pueden ser negativos, entonces las cosas son más difíciles: debe realizar la prueba de forma que la prueba en sí no pueda causar el desbordamiento.

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

Si eres yendo a voto negativo, se considera cortés dejar un comentario explicando lo que sientes que es inútil o incorrecto. – caf

+0

Por cierto, ¿puedes comentar sobre el rendimiento de esta solución en comparación con otras soluciones alternativas? – Pacerier

+6

Tiene poco sentido comparar el rendimiento con una solución incorrecta. ¿Qué otra solución correcta tenías en mente? – caf

Cuestiones relacionadas