Estoy trabajando en un proyecto grande que generalmente funciona bien, pero muestra problemas graves una vez que el tamaño de los datos de entrada supera algunas limitaciones.
Estos problemas (se sospecha) solo se deben a desbordamientos de enteros con signo como estos:
int a, o;
// Initialize a and o
int x = (a+o) >> 1);
Obviamente, una vez que la suma de a y o se desborda (se hace mayor que 2^31-1), x ya no es la media de a y o.
¿Existe una forma genérica de encontrar todos estos desbordamientos de enteros en un programa en ejecución?
Estoy pensando en una herramienta como Valgrind o una extensión GDB que se rompe en cada instrucción aritmética de enteros, toma los parámetros y compara el resultado correcto (calculado con un tipo de datos de mayor tamaño o aritmética de precisión arbitraria) con el resultado real. Si los resultados difieren, debería generar una advertencia, desencadenar una interrupción de depuración o algo como esto.
Sé cómo verificar una sola instrucción aritmética en busca de desbordamientos (por ejemplo, verificar el signo de adiciones), sin embargo, debido a la gran cantidad de código, no es una solución viable para mí revisar todo el proyecto e insertar el código de verificación en todas partes a mano.
Para una gran base de código, Coverity
es una buena herramienta No estoy seguro de que lo detecte all
el número entero se desborda o no, pero vale la pena intentarlo.
naranjaperro
Debe trabajar con todo el código y determinar cuál es el límite en la entrada del usuario y validar la entrada. Es posible que también deba volver a escribir algunos algoritmos para reducir los problemas de desbordamiento.
Como el ejemplo que das no funciona para valores negativos, deberías usar un unsigned int
de todos modos, dándote un orden extra de magnitud ya.
Editar:
gcc tiene el -ftrapv
opción, pero esto por lo general, en realidad no hace nada solo funciona con -O0
. Si está adoptando el enfoque de atrapar los desbordamientos cuando ocurren, aún necesita un buen conocimiento del código para poder probarlo completamente.
-
Sé aproximadamente cuál es el límite en la entrada del usuario. El problema de trabajar con el código es que el proyecto tiene más de 200 000 líneas (199 000 de ellas no escritas por mí) y me temo que sería bastante imposible verificarlas a mano en busca de código propenso a desbordarse.
– ChrisM
4 de enero de 2011 a las 14:12
-
@ChrisM: si se encuentra en una posición en la que no puede confiar en que el código que otra persona escribió es correcto, entonces probablemente no debería usarlo. Deben existir prácticas comerciales para lidiar con cosas como esta (revisiones, pruebas, etc.). Si solo eres tú con este código y nadie más alrededor, necesitarás pasar un tiempo leyéndolo todo de todos modos.
– perro naranja
4 de enero de 2011 a las 14:45
-
Está bien, es una pena. Solo esperaba que hubiera una manera de encontrar las secciones problemáticas en el código (probablemente una docena, o algunas más) automáticamente.
– ChrisM
4 de enero de 2011 a las 15:11
-
El “por lo general, en realidad no hace nada” advertencia para
-ftrapv
solo se aplica cuando se compila con optimización. Con-O0
debería funcionar bien.– café
5 de enero de 2011 a las 2:41
-
@caf: todavía no me funciona con -O0. Verifiqué comparando los binarios generados con y sin -ftrapv, y encontré que eran completamente idénticos.
– ChrisM
6 de enero de 2011 a las 15:46
¿Qué tal un script que pasa por el código y reemplaza todo “a+b” con DEBUGADD(a,b) – donde puedes hacer:
#ifdef DEBUG
int addFn(int a, int b) {
long long m;
int n;
m = (long long)a + (long long)b;
n = a + b;
if (m != (long long)n)
printf("PANIC!\n");
return n;
}
#define DEBUGADD(a,b) addFn(a,b)
#else
#define DEBUGADD(a,b) ((a)+(b))
#endif
-
Solo asegúrese de que su secuencia de comandos maneje los espacios en blanco, las conversiones, el orden de las operaciones y los tipos de devolución correctamente 🙂
– Karmastán
4 de enero de 2011 a las 16:31
-
Mejor sería simplemente
assert(((a <= 0) || (b <= INT_MAX - a)) && ((a >= 0) || (b >= INT_MIN - a)))
ya que una expresión similar funcionará paralong
ylong long
también.– café
5 de enero de 2011 a las 2:30