2011-01-04 28 views
15

Sto lavorando a un progetto di grandi dimensioni che in genere funziona correttamente, ma mostra problemi gravi una volta che le dimensioni dei dati di input superano alcune limitazioni.Come trovare (tutto) il numero intero di overflow in un programma C?

Questi problemi sono (sospetta) solo per intero con segno trabocca come questi:

int a, o; 
// Initialize a and o 
int x = (a+o) >> 1); 

Ovviamente, una volta che la somma di A e O overflow (diventa più grande di 2^31-1), x non è più lunga la media di a e o.

Esiste un modo generico per trovare tutti questi integer overflow in un programma in esecuzione?

Sto pensando a uno strumento come Valgrind o un'estensione GDB che rompe ad ogni intera istruzione aritmetica, prende i parametri e confronta il risultato corretto (calcolato con un datatype di dimensioni maggiori o aritmetica di precisione arbitraria) con il risultato effettivo . Se i risultati sono diversi, dovrebbe emettere un avviso, attivare un'interruzione di debug o qualcosa del genere.

Lo so, come controllare una singola istruzione aritmetica per gli overflow (ad esempio, controllare il segno per le aggiunte), tuttavia a causa della grande quantità di codice, non è una soluzione praticabile per me per passare attraverso l'intero progetto e inserire controllo codice ovunque a mano.

risposta

3

Per larga base di codice, Coverity è un buon strumento. Non sono sicuro che rileverà il numero intero di all overflow o no, ma vale la pena provare.

2

È necessario lavorare su tutto il codice e capire quale sia il limite per l'input dell'utente e convalidare l'input. Potrebbe anche essere necessario riscrivere alcuni algoritmi per ridurre i problemi di overflow.

Come nell'esempio fornito non funziona con valori negativi, si dovrebbe comunque usare uno unsigned int, dando già un ordine di grandezza in più.

Edit: gcc ha la possibilità -ftrapv, ma questo di solito in realtà non fa nulla funziona solo con -O0. Se stai prendendo l'approccio di trapping overflow quando accadono, hai comunque bisogno di una buona conoscenza del codice per testarlo completamente.

+0

So approssimativamente, qual è il limite per l'input dell'utente. Il problema con il lavoro attraverso il codice è che il progetto ha più di 200k linee (199k di esse non scritte da me) e temo che sarebbe praticamente impossibile controllarle a mano per codice soggetto a overflow. – ChrisM

+0

@ChrisM - Se sei in una posizione in cui non ti puoi fidare di quel codice che qualcun altro ha scritto è corretto, probabilmente non dovresti usarlo. Dovrebbero essere in atto pratiche commerciali per gestire cose come questa (recensioni, test, ecc.). Se sei solo tu con questo codice e nessun altro in giro, avrai bisogno di passare un po 'di tempo a leggerlo comunque. – OrangeDog

+0

Ok, è un peccato. Speravo solo che ci fosse un modo per trovare automaticamente le sezioni problematiche nel codice (probabilmente una dozzina o più). – ChrisM

0

ne dite di uno script che passa attraverso il codice e sostituisce tutti "A + B" con DEBUGADD (a, b) - in cui si può fare:

#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 
+3

Basta assicurarsi che lo script gestisce gli spazi, calchi, ordine delle operazioni, e tipi restituiti correttamente :) – Karmastan

+0

Meglio sarebbe solo 'assert (((a <= 0) || (b <= INT_MAX - a)) && ((a> = 0) || (b> = INT_MIN - a))) ', poiché un'espressione simile funzionerà anche per' long' e 'long long'. – caf

Problemi correlati