2009-09-16 22 views
7

C'è un modo per trovare potenziali overflow numerici nel codice Java, utilizzando l'IDE Eclipse? Per esempio ...Come trovare potenziali overflow numerici nel codice Java, usando Eclipse?

long aLong = X * Y * Z; 

... dove X, Y, e Z sono interi e il risultato può traboccare Integer.MAX_VALUE. (Si noti che, forse in modo anti-intuitivo, se il risultato in questo esempio supera il valore Integer.MAX_VALUE, aLong verrà assegnato il valore di overflow errato).

Ho cercato nelle impostazioni di Eclipse di Avvisi, regole PMD e regole FindBugs e non riesco a trovare alcuna impostazione per aiutare con questo. Un collega osserva che IntelliJ avvertirà di questo ... e odio dover ammettere che non posso fare lo stesso con Eclipse. ;-)


Precisazione 1: Non sto cercando qualcosa che dà 0 falsi positivi ... solo avvertimenti che "si può avere un problema di overflow qui",

Precisazione 2:. Questa è desiderato in "tempo di sviluppo" ... il che significa che, nello stesso momento in cui Eclipse sta cercando importazioni inutilizzate, PMD sta verificando le sue regole, ecc.

+0

Quindi vuoi essere avvisato di qualsiasi operazione aritmetica? a = x + y può overflow se a, xey sono lo stesso tipo integrale – Mark

+0

Mi piacerebbe avere anche questo controllo, ma solo per la moltiplicazione. Sto facendo la programmazione di contest e in genere i valori sono fino a 10^9, quindi l'aggiunta non è un problema, ma la moltiplicazione è e voglio essere avvertita, altrimenti dimentico il trucco 1L * x * y' ... – Betlista

risposta

-1

potrebbe essere possibile eseguire il calcolo con java.math.BigInteger e confrontare il risultato con

new java.math.BigInteger(String.valueOf(Long.MAX_VALUE)) 
+0

Che è un modo per fare il calcolo senza errori, ma non per rilevare se un calcolo è soggetto a un particolare tipo di errore, che è quello che la domanda sta ponendo. – Carl

0

Lo vuoi al momento della compilazione? Non ho visto un ambiente per farlo.

Se si davvero lo vuole, la soluzione migliore è più probabile scrivere un nuovo set di regole per PMD?

0

Quale sarebbe il risultato previsto per questo?

long testMethod() { 
    long aLong = Integer.MAX_VALUE + doesMethodContainAnOverflow ("testMethod") ? 0 : 1; 

    return aLong; 
} 

ha un overflow solo se non è presente un overflow.

C'è un potenziale overflow per qualsiasi operazione di numero intero di rappresentazione fissa; determinare se c'è un vero e proprio overflow è banalmente convertibile al problema dell'arresto. Ciò non significa che IntelliJ non abbia un certo euristico per avvisarti in alcuni casi: potresti, per esempio, tracciare i limiti superiore e inferiore di ogni operazione numerica attraverso un programma e ottenere una risposta nel caso peggiore, ma scrivere un una regola precisa non sarebbe né banale né decidibile.

+0

La domanda è per * potenziali * trabocchi, che è la risposta del caso peggiore, che come si fa notare, è decidibile. La funzione non riguarda la decisione di overflow, è più come richiamare l'attenzione su cose che il programmatore potrebbe non riconoscere come potenziali punti di overflow, anche se il rumore è probabilmente piuttosto elevato (ad esempio l'aggiunta semplice di numeri interi variabili, ad esempio). – Carl

+0

Qualcuno sta leggendo GEB – Jherico

0

Ciò richiederebbe una profonda analisi di un algoritmo o semplicemente un avviso per ogni operazione aritmetica che coinvolge variabili.

EDIT: Oh, intendi che se X, Y e Z sono numeri interi, allora la moltiplicazione sarebbe su numeri interi e solo allora assegnata a un Lungo? IntelliJ Idea lo mostrerà come un avvertimento, ma l'ispezione è disattivata per impostazione predefinita.

+0

Sì, il tuo EDIT è corretto. Sto solo cercando un avvertimento simile a quello che fa Idea IntelliJ. – dirtyvagabond

+0

È possibile scrivere una regola PMD di FindBugs, ma non penso che ne valga la pena. –

1

In FindBugs descrizione del rivelatore del FindPuzzlers contiene

ICAST_INTEGER_MULTIPLY_CAST_TO_LONG (ICAST, STILE): Risultato del cast moltiplicazione integer lungo

ma in qualche modo non può fare questo rilevare il problema nel codice seguente:

final int x = 10000; 
    final int y = 10000; 
    final int z = 10000; 
    final long aLong = x * y * z; 
    System.out.println(aLong); 
+0

Ci sono due impostazioni nel plugin Eclipse - "Grado minimo da segnalare" e "Confidenza minima da segnalare". Questo ha il rango 17 e viene mostrato quando la sicurezza è impostata su Bassa o Media ... – Betlista

4

Se non sai cosa X potrebbe essere, potrebbe essere il caso peggiore.Quindi, qual è il caso peggiore:

int X = Integer.MAX_VALUE; 
long aLong = X + 1; 

Conclusione: Non vuoi che Eclipse ti avvisa di tutto.

Se si vuole risolvere integer overflow

long aLong = X * Y * Z; //you could write 
long aLong = (long)X * Y * Z; 

Conclusione: Questo non sarebbe risolvere i problemi lungo overflow. Se si vuole risolvere li si dovrebbe scrivere codice come:

BigInteger tmp = BigInteger.valueOf(X).multiply(BigInteger.valueOf(Y)).multiply(BigInteger.valueOf(Z)); 
if(BigInteger.valueOf(Long.MAX_VALUE).compareTo(tmp)>=0){ 
    long aLong = tmp.longValue(); 
}else{ 
    System.out.println("Overflow"); 
} 

Ma questo si verificherà solo se il valore risultante potrebbe adattarsi a lungo. Ma stai chiedendo, se durante il calcolo si è verificato "Overflow". Ciò significherebbe dopo ogni calcolo che dovresti controllare per questo.

Se si desidera scrivere uno strumento per eclissi che analizzi l'intero file sorgente per trovare questo, quindi non ti sto fermando. Ma sarebbe molto più semplice ricordare i seguenti valori:

/*11111111111111111111111111111111*/int Y = -1; //-1 
/*11111111111111111111111111111111*/int QRY = (Y >> 1); //-1 
/*11111111111111111111111111111110*/int QLY = (Y << 1); //-2 
/*11111111111111111111111111111110*/int QLX = (X << 1); //-2 
/*11000000000000000000000000000000*/int QRZ = (Z >> 1); //-1073741824 
/*10000000000000000000000000000000*/int Z = Integer.MIN_VALUE; //-2147483648 
/*01111111111111111111111111111111*/int X = Integer.MAX_VALUE; // 2147483647 
/*00111111111111111111111111111111*/int QRX = (X >> 1); // 1073741823 
/*00000000000000000000000000000000*/int QLZ = (Z << 1); // 0 
Problemi correlati