2009-09-16 12 views
7

Czy istnieje sposób na znalezienie potencjalnych przekroczeń liczbowych w kodzie Java, korzystając z IDE Eclipse? Na przykład ...Jak znaleźć potencjalne przepełnienie liczbowe w kodzie Java, używając Eclipse?

long aLong = X * Y * Z; 

..., gdzie X, Y i Z są typu int i wynik może przelewać Integer.MAX_VALUE. (Zauważ, że być może sprzecznym z intuicją, jeśli wynik w tym przykładzie przekroczy wartość Integer.MAX_VALUE, aLong zostanie przypisana błędna przepełniona wartość).

Sprawdziłem ustawienia ostrzeżenia Eclipse, zasady PMD i reguły FindBugs i nie mogę znaleźć żadnego ustawienia, które by im pomogło. Współpracownik zauważa, że ​​IntelliJ ostrzega o tym ... i nie chciałbym przyznać, że nie mogę zrobić tego samego z Eclipse. ;-)


Wyjaśnienie 1: Nie szukam czegoś, co daje 0 fałszywych alarmów ... tylko ostrzeżenia, że ​​„mogą mieć problem przepełnienia tutaj”

Wyjaśnienie 2:. To jest pożądane w "czasie rozwoju" ... co oznacza, że ​​na tym samym etapie, w którym Eclipse szuka niewykorzystanego importu, PMD sprawdza jego zasady, itp.

+0

Więc chcesz być ostrzeżony przed operacją arytmetyczną? a = x + y może przepełnić się, jeśli a, x i y są tymi samymi integralnymi typami: – Mark

+0

Chciałbym mieć również taki sprawdzian, ale tylko dla mnożenia. Robię programowanie konkursowe i zazwyczaj wartości są do 10^9, więc dodawanie nie jest problemem, ale mnożenie jest i chcę być ostrzeżony, w przeciwnym razie zapomnę podstęp "1L * x * y" ... – Betlista

Odpowiedz

-1

może być możliwe obliczenie za pomocą java.math.BigInteger i porównanie wyniku z

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

To to sposób wykonywania obliczeń bez błędów, ale nie do wykrycia, czy obliczenie podlega szczególnemu rodzajowi błędu, o co pyta. – Carl

0

Chcesz tego podczas kompilacji? Nie widziałem ustawienia, aby to zrobić.

Jeśli chcesz, naprawdę, najlepiej jest napisać nowy zestaw reguł dla PMD?

0

Jaki byłby oczekiwany rezultat?

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

    return aLong; 
} 

ma przepełnienie tylko wtedy, gdy nie ma w nim przepełnienia.

Istnieje potencjalne przepełnienie dla dowolnej stałej operacji reprezentacji całkowitej; ustalenie, czy rzeczywisty przelew jest trywialnie wymienialny na problem z zatrzymaniem. Co nie znaczy, że IntelliJ nie ma jakiejś heurystyki, aby ostrzec cię w niektórych przypadkach - możesz na przykład śledzić górne i dolne ograniczenia dowolnej operacji numerycznej poprzez program i uzyskać najgorszą możliwą odpowiedź, ale piszesz dokładna zasada nie byłaby ani trywialna, ani rozstrzygająca.

+0

Pytanie dotyczy * potencjalnej * przepełnienia, która jest najgorszą możliwą odpowiedzią, która, jak sam wskazywałeś, jest rozstrzygająca. Funkcja nie polega na decydowaniu o przepełnieniach w każdym razie, to raczej zwracanie uwagi na rzeczy, które programista mógł nie rozpoznać jako potencjalne punkty przepełnienia, chociaż hałas jest prawdopodobnie dość wysoki (proste dodanie zmiennych całkowitych powinno je wyłączyć, na przykład). – Carl

+0

Ktoś czytał GEB – Jherico

0

Wymagałoby to głębokiej analizy algorytmu lub po prostu ostrzeżenia dla każdej operacji arytmetycznej, która obejmuje zmienne.

EDYCJA: Oh, masz na myśli, że jeśli X, Y i Z są liczbami całkowitymi, to mnożenie będzie na liczbach całkowitych i tylko wtedy przypisane do dłuższej? IntelliJ Idea wyświetli to ostrzeżenie, ale inspekcja jest domyślnie wyłączona.

+0

Tak, twoja EDYCJA jest poprawna. Po prostu szukam ostrzeżenia podobnego do tego, co robi IntelliJ Idea. – dirtyvagabond

+0

Możesz napisać PMD reguły FindBugs, ale nie sądzę, że warto. –

1

W FindBugs opis detektora FindPuzzlers zawiera

ICAST_INTEGER_MULTIPLY_CAST_TO_LONG (ICAST, styl): Wynik z całkowitą mnożenia obsady długim

ale jakoś nie mogę zrobić tego wykryć problem w poniższym kodzie:

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

Istnieją dwa ustawienia wtyczki Eclipse - "Minimalna pozycja do raportu" i "Minimalne zaufanie do raportu". Ma ona 17 pozycję i jest wyświetlana, gdy zaufanie jest ustawione na Niski lub Średni ... – Betlista

4

Jeśli nie wiesz, czym może być X, może to być najgorszy przypadek.A więc najgorszy przypadek:

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

Wniosek: Nie chcesz, aby Eclipse ostrzegał Cię o wszystkim.

Jeśli chcesz naprawić całkowitą przepełnienie

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

Wniosek: Nie byłoby rozwiązać problemy długo przelewowy. Jeśli chcesz je naprawić należy wpisać kod jak:

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

Ale to będzie tylko sprawdzić, czy otrzymana wartość mogła zmieścić się w długi. Ale pytasz, czy podczas obliczeń zdarzył się "Overflow". Oznaczałoby to, że po każdym obliczeniu musiałbyś to sprawdzić.

Jeśli chcesz napisać narzędzie do zaćmienia, które analizuje cały plik źródłowy, aby go znaleźć, to nie zatrzymuję cię. Ale o wiele łatwiej byłoby zapamiętać następujące wartości:

/*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 
Powiązane problemy