2009-09-16 6 views
7

Y a-t-il un moyen de trouver des débordements numériques potentiels dans le code Java, en utilisant l'IDE Eclipse? Par exemple ...Comment trouver des débordements numériques potentiels dans le code Java, en utilisant Eclipse?

long aLong = X * Y * Z; 

... où X, Y et Z sont ints et le résultat peut déborder Integer.MAX_VALUE. (Notez que, peut-être contre-intuitivement, si le résultat de cet exemple déborde de Integer.MAX_VALUE, on attribuera à aLong la valeur débordée erronée).

J'ai regardé les paramètres Avertissements d'Eclipse, les règles PMD et les règles FindBugs et je ne trouve aucun paramètre pour vous aider. Un collègue remarque qu'IntelliJ va prévenir à ce sujet ... et je détesterais devoir admettre que je ne peux pas faire la même chose avec Eclipse. ;-)


Précision 1: Je ne cherche pas quelque chose qui donne de faux positifs 0 ... juste des avertissements que « vous pourriez avoir un problème de débordement ici »,

Précision 2:. Cette est souhaité à "temps de développement" ... ce qui signifie, au même stade que Eclipse cherche des importations inutilisées, PMD vérifie ses règles, etc

+0

Vous voulez donc être averti de toute opération arithmétique? a = x + y peut déborder si a, x et y sont du même type intégral – Mark

+0

J'aimerais aussi avoir un tel contrôle, mais seulement pour la multiplication. Je fais de la programmation de concours et typiquement les valeurs vont jusqu'à 10^9, donc l'addition n'est pas un problème, mais la multiplication est et je veux être prévenu, sinon j'oublie le tour de 1L * x * y' ... – Betlista

Répondre

-1

peut être que vous pourriez faire votre calcul avec java.math.BigInteger et de comparer le résultat avec

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

est une façon de faire le calcul sans erreurs, mais de ne pas détecter si un calcul est sujet à un type d'erreur particulier, ce que demande la question. – Carl

0

Vous voulez cela au moment de la compilation? Je n'ai pas vu de réglage pour le faire.

Si vous vraiment voulez le, le meilleur pari est le plus susceptible d'écrire un nouveau jeu de règles pour PMD?

0

Quel serait le résultat attendu?

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

    return aLong; 
} 

il a un débordement uniquement s'il n'y a pas de débordement.

Il existe un dépassement de capacité potentiel pour toute opération d'entier de représentation fixe; déterminer s'il y a un dépassement réel est trivialement convertible en problème d'arrêt. Cela ne signifie pas qu'IntelliJ n'a pas d'heuristique pour vous avertir dans certains cas - vous pouvez, par exemple, suivre les limites supérieures et inférieures de n'importe quelle opération numérique à travers un programme et obtenir une réponse dans le pire des cas, mais en écrivant règle précise ne serait ni triviale ni décidable.

+0

La question est pour les débordements * potentiels *, ce qui est la réponse la plus défavorable, qui, comme vous l'avez souligné, est décidable. La fonction n'est pas de décider des débordements, mais plutôt d'attirer l'attention sur des choses que le programmeur n'aurait pas reconnu comme des points de débordement potentiels, bien que le bruit soit probablement assez élevé (la simple addition d'entiers variables devrait le déclencher, par exemple). – Carl

+0

Quelqu'un a lu GEB – Jherico

0

Cela nécessiterait soit une analyse approfondie d'un algorithme, soit simplement un avertissement pour chaque opération arithmétique impliquant des variables.

EDIT: Oh, voulez-vous dire que si X, Y et Z sont des entiers, alors la multiplication serait sur des entiers et seulement ensuite assignée à aLong? IntelliJ Idea le montrera comme un avertissement mais l'inspection est désactivée par défaut.

+0

Oui, votre EDIT est correct. Je cherche juste un avertissement similaire à ce que fait IntelliJ Idea. – dirtyvagabond

+0

Vous pouvez écrire une règle PMD de FindBugs, mais je ne pense pas que cela en vaille la peine. –

1

En FindBugs la description du détecteur de FindPuzzlers contient

ICAST_INTEGER_MULTIPLY_CAST_TO_LONG (ICAST, STYLE): Résultat de la fonte de multiplication entier et à long

mais je ne peux en quelque sorte pas en faire détecter le problème dans le code suivant:

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

Il y a deux réglages dans le plugin Eclipse - "Minimum rank to report" et "Minimum confidence to report". Il a le rang 17 et est affiché lorsque la confiance est définie sur Faible ou Moyen ... – Betlista

4

Si vous ne savez pas ce que X pourrait être, cela pourrait être le pire des cas.Donc, quel est le pire des cas:

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

Conclusion: Vous ne voulez pas qu'Eclipse vous avertisse de tout.

Si vous voulez fixer débordement d'entier de

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

Conclusion: Ce ne serait pas résoudre les problèmes de débordement de long. Si vous voulez les corriger vous devez écrire le code comme:

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"); 
} 

Mais cela ne vérifie si la valeur résultante pourrait tenir dans longtemps. Mais vous demandez, si au cours du calcul "débordement" est arrivé. Cela signifierait après chaque calcul que vous auriez besoin de vérifier cela.

Si vous voulez écrire un outil pour eclipse qui analyse le fichier source entier pour le trouver, alors je ne vous arrête pas. Mais il serait tout simplement beaucoup plus facile de se souvenir des valeurs suivantes:

/*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 
Questions connexes