Как найти возможные числовые переполнения в коде Java, используя Eclipse? - PullRequest
7 голосов
/ 17 сентября 2009

Есть ли способ найти потенциальные числовые переполнения в коде Java, используя Eclipse IDE? Например ...

long aLong = X * Y * Z;

... где X, Y и Z - целые числа, и результат может переполнить Integer.MAX_VALUE. (Обратите внимание, что, возможно, нелогично, если результат в этом примере переполняет Integer.MAX_VALUE, aLong будет присвоено ошибочное переполненное значение).

Я посмотрел в настройках предупреждений Eclipse, правилах PMD и правилах FindBugs и не могу найти ни одной настройки, чтобы помочь с этим. Сотрудник отмечает, что IntelliJ предупредит об этом ... и я не хотел бы признавать, что не могу сделать то же самое с Eclipse. ; -)


Разъяснение 1: я не ищу что-то, что дает 0 ложных срабатываний ... просто предупреждения о том, что "у вас здесь может быть проблема переполнения".

Пояснение 2: Это желательно в «время разработки» ... то есть на той же стадии, когда Eclipse ищет неиспользуемый импорт, PMD проверяет свои правила и т. Д.

Ответы [ 6 ]

4 голосов
/ 18 сентября 2009

Если вы не знаете, что может быть X, это может быть наихудший случай. Итак, какой наихудший случай:

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

Вывод: вы не хотите, чтобы Eclipse предупреждала вас обо всем.

Если вы хотите исправить целочисленное переполнение

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

Вывод: это не устранит проблемы с длительным переполнением. Если вы хотите исправить их, вы должны написать код вроде:

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

Но это только проверит, может ли полученное значение соответствовать длинному. Но вы спрашиваете, произошло ли во время расчета «переполнение». Это будет означать, что после каждого расчета вам нужно будет это проверить.

Если вы хотите написать инструмент для затмения, который анализирует весь исходный файл, чтобы найти это, то я вас не остановлю. Но было бы намного проще запомнить следующие значения:

 /*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
1 голос
/ 17 сентября 2009

В FindBugs описание детектора FindPuzzlers содержит

ICAST_INTEGER_MULTIPLY_CAST_TO_LONG (ICAST, STYLE): результат приведения целочисленного умножения к длинному

но почему-то я не могу заставить это обнаружить проблему в следующем коде:

    final int x = 10000;
    final int y = 10000;
    final int z = 10000;
    final long aLong = x * y * z;
    System.out.println(aLong);
0 голосов
/ 17 сентября 2009

Это потребует либо глубокого анализа алгоритма, либо просто выдаст предупреждение за каждую арифметическую операцию, которая включает переменные.

РЕДАКТИРОВАТЬ: О, ты имеешь в виду, что если X, Y и Z являются целыми числами, то умножение будет на целых и только тогда присвоено aLong? IntelliJ Idea покажет это как предупреждение, но проверка по умолчанию отключена.

0 голосов
/ 17 сентября 2009

Каков будет ожидаемый результат для этого?

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

     return aLong;
 }

переполнение происходит только в том случае, если в нем нет переполнения.

Существует потенциальное переполнение для любой целочисленной операции с фиксированным представлением; Определение того, есть ли фактическое переполнение, легко преобразуется в проблему остановки. Это не означает, что у IntelliJ нет эвристики для предупреждения вас в некоторых случаях - вы можете, например, отследить верхнюю и нижнюю границы любой числовой операции через программу и получить ответ в худшем случае, но написав Точное правило не будет ни тривиальным, ни решаемым.

0 голосов
/ 17 сентября 2009

Вы хотите это во время компиляции? Не видел настройки для этого.

Если вы действительно хотите этого, то лучше всего написать новый набор правил для PMD?

0 голосов
/ 17 сентября 2009

может быть, вы могли бы сделать свой расчет с java.math.BigInteger и сравнить результат с

new java.math.BigInteger(String.valueOf(Long.MAX_VALUE))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...