Język | Unsigned integer | Signed integer |
---|---|---|
Ada | modulo the type’s modulus | raise Constraint_Error |
C/C++ | modulo power of two | undefined behavior |
C# | modulo power of 2 in unchecked context; System.OverflowException jest podniesiony w sprawdzonym kontekście |
|
Java | N/A | modulo potęga dwójki |
JavaScript | wszystkie liczby są podwójnejzmiennoprzecinkowe podwójnej precyzji, z wyjątkiem nowej liczby BigInt | |
MATLAB | Builtin integers saturate. Stałe -punktowe liczby całkowite konfigurowalne do zawijania lub nasycania | |
Python 2 | N/A | konwertuj do typu long (bigint) |
Seed7 | N/A | raise OVERFLOW_ERROR |
Scheme | N/A | konwertuj do bigNum |
Simulink | konfigurowalny do zawijania lub nasycania | |
Smalltalk | N/A | convert to LargeInteger |
Swift | Powoduje błąd, chyba że użyto specjalnych operatorów przepełnienia. |
DetectionEdit
Run-time overflow detection implementation UBSan
is available for C compilers.
W Javie 8, istnieją przeciążone metody, na przykład jak Math.addExact(int, int)
, które będą rzucać ArithmeticException
w przypadku przepełnienia.
Komputerowy zespół reagowania kryzysowego (CERT) opracował model liczb całkowitych As-if Infinitely Ranged (AIR), w dużej mierze zautomatyzowany mechanizm eliminacji przepełnienia i obcięcia liczb całkowitych w C/C++ przy użyciu obsługi błędów w czasie wykonywania.
AvoidanceEdit
Przez przydzielanie zmiennych z typami danych, które są wystarczająco duże, aby pomieścić wszystkie wartości, które mogą być ewentualnie obliczane i przechowywane w nich, zawsze można uniknąć przepełnienia. Nawet jeśli dostępna przestrzeń lub stałe typy danych dostarczane przez język programowania lub środowisko są zbyt ograniczone, aby umożliwić defensywne przydzielanie zmiennych o dużych rozmiarach, poprzez staranne zamawianie operacji i sprawdzanie operandów z wyprzedzeniem, często możliwe jest zapewnienie a priori, że wynik nigdy nie będzie większy niż może być przechowywany. Narzędzia analizy statycznej, weryfikacja formalna i techniki projektowania przez umowę mogą być użyte do bardziej pewnego i solidnego zapewnienia, że przepełnienie nie może przypadkowo powstać.
HandlingEdit
Jeśli przewiduje się, że przepełnienie może wystąpić, to testy mogą być wstawione do programu, aby wykryć, kiedy to się stanie lub ma się stać, i wykonać inne przetwarzanie, aby to złagodzić. Na przykład, jeśli ważny wynik obliczony na podstawie danych wejściowych użytkownika przepełni się, program może się zatrzymać, odrzucić dane wejściowe i być może poprosić użytkownika o inne dane wejściowe, zamiast kontynuować program z nieważnymi przepełnionymi danymi wejściowymi i prawdopodobnie nieprawidłowym działaniem w konsekwencji. Ten pełny proces może być zautomatyzowany: możliwa jest automatyczna synteza handler’a dla przepełnienia całkowitego, gdzie handler jest na przykład czystym wyjściem.
CPU zazwyczaj mają sposób wykrywania tego, aby wspierać dodawanie liczb większych niż ich rozmiar rejestru, zwykle używając bitu stanu; technika ta jest nazywana arytmetyką wielokrotnej precyzji.Tak więc możliwe jest dodanie dwóch liczb, każda o szerokości dwóch bajtów, używając tylko dodawania bajtów w krokach: najpierw dodaj niskie bajty, a następnie dodaj wysokie bajty, ale jeśli konieczne jest przeprowadzenie z niskich bajtów, jest to przepełnienie arytmetyczne dodawania bajtów i konieczne staje się wykrycie i inkrementacja sumy wysokich bajtów.
Obsługa możliwego przepełnienia obliczeń może czasami stanowić wybór między wykonaniem kontroli przed faktycznym obliczeniem (w celu określenia, czy przepełnienie wystąpi, czy nie), lub po nim (w celu rozważenia, czy prawdopodobnie wystąpiło na podstawie wartości wynikowej). Należy zachować ostrożność w przypadku tego drugiego wyboru. Po pierwsze, ponieważ może to nie być niezawodna metoda wykrywania (na przykład, dodanie niekoniecznie musi być zawinięte do niższej wartości). Po drugie, ponieważ samo wystąpienie przepełnienia może być w niektórych przypadkach niezdefiniowanym zachowaniem. W języku programowania C, przepełnienie niepodpisanych typów całkowitych powoduje zawijanie, jednak przepełnienie podpisanych typów całkowitych jest niezdefiniowanym zachowaniem; w konsekwencji kompilator C może swobodnie zakładać, że programista upewnił się, że podpisane przepełnienie nie może prawdopodobnie wystąpić, a zatem może cicho zoptymalizować każde sprawdzenie po obliczeniu, które obejmuje sprawdzenie wyniku w celu wykrycia go, nie dając programiście żadnego ostrzeżenia, że zostało to zrobione. Dlatego zaleca się, aby zawsze preferować implementację kontroli przed obliczeniami, a nie po nich.
Explicit propagationEdit
Jeśli wartość jest zbyt duża, aby ją przechowywać, można jej przypisać specjalną wartość wskazującą, że wystąpiło przepełnienie, a następnie wszystkie kolejne operacje zwracają tę wartość flagi. Takie wartości są czasami określane jako NaN, czyli „not a number”. Jest to przydatne, aby problem mógł być sprawdzony raz na końcu długiego obliczenia, a nie po każdym kroku. Jest to często obsługiwane w sprzęcie zmiennoprzecinkowym zwanym FPU.
Obsługa języków programowaniaEdit
Języki programowania implementują różne metody łagodzenia przeciwko przypadkowemu przepełnieniu: Ada, Seed7 (i niektóre warianty języków funkcjonalnych), wyzwalają warunek wyjątku przy przepełnieniu, podczas gdy Python (od 2.4) płynnie konwertuje wewnętrzną reprezentację liczby, aby dopasować ją do jej wzrostu, ostatecznie reprezentując ją jako long
– której możliwości są ograniczone tylko przez dostępną pamięć.
W językach z natywnym wsparciem dla arytmetyki arbitralnej precyzji i bezpieczeństwa typu (takich jak Python, Smalltalk lub Common Lisp), liczby są promowane do większego rozmiaru automatycznie, gdy wystąpią przepełnienia, lub wyjątki rzucane (warunki sygnalizowane), gdy istnieje ograniczenie zakresu. Używanie takich języków może być więc pomocne w złagodzeniu tego problemu. Jednakże, w niektórych takich językach nadal możliwe są sytuacje, w których może dojść do przepełnienia liczby całkowitej. Przykładem jest jawna optymalizacja ścieżki kodu, która jest uważana przez profiler za wąskie gardło. W przypadku Common Lisp, jest to możliwe poprzez użycie jawnej deklaracji do przypisania zmiennej typu do słowa o rozmiarze maszynowym (fixnum) i obniżenia poziomu bezpieczeństwa typu do zera dla konkretnego bloku kodu.
W ostrym kontraście do starszych języków, takich jak C, niektóre nowsze języki, takie jak na przykład Rust, zapewniają wbudowaną funkcjonalność, która pozwala na łatwe wykrywanie i wybór użytkownika, w jaki sposób przepełnienie powinno być obsługiwane w każdym przypadku. W Rust, podczas gdy użycie podstawowych operatorów matematycznych naturalnie pozbawione jest takiej elastyczności, użytkownicy mogą alternatywnie wykonywać obliczenia za pomocą zestawu metod dostarczanych przez każdy z prymitywnych typów całkowitych. Metody te dają użytkownikom kilka możliwości wyboru pomiędzy wykonaniem operacji „sprawdzonej” (lub „przepełnienia”) (która wskazuje, czy przepełnienie wystąpiło poprzez typ zwrotu); operacją „niezaliczoną”; operacją, która wykonuje zawijanie lub operacją, która wykonuje nasycenie na granicach liczbowych.
Arytmetyka nasyconaEdit
W grafice komputerowej lub przetwarzaniu sygnałów, typowa jest praca na danych, które mają zakres od 0 do 1 lub od -1 do 1. Na przykład, weź obraz w skali szarości, gdzie 0 reprezentuje czerń, 1 reprezentuje biel, a wartości pomiędzy reprezentują odcienie szarości. Jedną z operacji, którą możemy chcieć wesprzeć jest rozjaśnienie obrazu poprzez pomnożenie każdego piksela przez stałą. Arytmetyka nasycona pozwala po prostu ślepo pomnożyć każdy piksel przez tę stałą, nie martwiąc się o przepełnienie, po prostu trzymając się rozsądnego wyniku, że wszystkie te piksele większe niż 1 (tj. „jaśniejsze niż białe”) po prostu stają się białe, a wszystkie wartości „ciemniejsze niż czarne” po prostu stają się czarne.