Ganzzahlüberlauf

Ganzzahlüberlaufbehandlung in verschiedenen Programmiersprachen
Sprache Ganzzahl ohne Vorzeichen Ganzzahl mit Vorzeichen
Ada modulo des Typs modulus raise Constraint_Error
C/C++ modulo power of two undefined behavior
C# modulo power of 2 in unchecked context; System.OverflowException wird im geprüften Kontext angehoben
Java N/A modulo Zweierpotenz
JavaScript alle Zahlen sind double-Präzisions-Gleitkommazahlen mit Ausnahme der neuen BigInt
MATLAB Builtin-Ganzzahlen sättigen. Fest-Punkt-Ganzzahlen konfigurierbar, um umzubrechen oder zu sättigen
Python 2 N/A in Long-Typ konvertieren (bigint)
Seed7 N/A raise OVERFLOW_ERROR
Scheme N/A Konvertieren in bigNum
Simulink Konfigurierbar für Wrap oder Saturate
Smalltalk N/A convert to LargeInteger
Swift Verursacht Fehler, wenn nicht spezielle Überlaufoperatoren verwendet werden.

DetectionEdit

Die Implementierung der Überlauferkennung zur Laufzeit UBSan ist für C-Compiler verfügbar.

In Java 8 gibt es überladene Methoden, wie z.B. Math.addExact(int, int), die im Falle eines Überlaufs ArithmeticException auslösen.

Das Computer Emergency Response Team (CERT) hat das As-if Infinitely Ranged (AIR) Integer-Modell entwickelt, einen weitgehend automatisierten Mechanismus zur Beseitigung von Integer-Überläufen und Abschneidungen in C/C++ mit Hilfe von Laufzeit-Fehlerbehandlung.

VermeidungBearbeiten

Durch Zuweisung von Variablen mit Datentypen, die groß genug sind, um alle Werte zu enthalten, die möglicherweise berechnet und in ihnen gespeichert werden können, ist es immer möglich, einen Überlauf zu vermeiden. Selbst wenn der verfügbare Platz oder die von einer Programmiersprache oder -umgebung bereitgestellten festen Datentypen zu begrenzt sind, um die defensive Zuweisung von Variablen mit großzügigen Größen zu ermöglichen, kann durch sorgfältige Anordnung der Operationen und vorherige Überprüfung der Operanden oft von vornherein sichergestellt werden, dass das Ergebnis niemals größer ist als gespeichert werden kann. Statische Analysewerkzeuge, formale Verifikation und Design-by-Contract-Techniken können eingesetzt werden, um sicherer und robuster zu gewährleisten, dass ein Überlauf nicht versehentlich auftreten kann.

HandlingEdit

Wenn zu erwarten ist, dass ein Überlauf auftreten kann, können Tests in das Programm eingefügt werden, um zu erkennen, wann er auftritt oder kurz davor ist, und andere Maßnahmen zu ergreifen, um ihn abzuschwächen. Wenn beispielsweise ein wichtiges Ergebnis, das aus einer Benutzereingabe berechnet wurde, überläuft, kann das Programm anhalten, die Eingabe zurückweisen und den Benutzer vielleicht zu einer anderen Eingabe auffordern, anstatt mit der ungültigen, überlaufenden Eingabe fortzufahren und infolgedessen möglicherweise eine Fehlfunktion zu verursachen. Dieser gesamte Prozess kann automatisiert werden: Es ist möglich, automatisch einen Handler für einen Integer-Überlauf zu synthetisieren, wobei der Handler z.B. ein sauberer Exit ist.

CPUs haben im Allgemeinen eine Möglichkeit, dies zu erkennen, um die Addition von Zahlen zu unterstützen, die größer als ihre Registergröße sind, typischerweise unter Verwendung eines Statusbits; die Technik wird als Multipräzisionsarithmetik bezeichnet.So ist es möglich, zwei Zahlen, die jeweils zwei Bytes breit sind, mit einer schrittweisen Byte-Addition zu addieren: zuerst werden die niedrigen Bytes addiert, dann die hohen Bytes, aber wenn es notwendig ist, die niedrigen Bytes auszuführen, ist dies ein arithmetischer Überlauf der Byte-Addition und es wird notwendig, die Summe der hohen Bytes zu erkennen und zu erhöhen.

Die Behandlung eines möglichen Überlaufs einer Berechnung kann manchmal die Wahl zwischen einer Prüfung vor der eigentlichen Berechnung (um festzustellen, ob ein Überlauf eintreten wird oder nicht) oder nach der Berechnung (um zu prüfen, ob ein Überlauf aufgrund des resultierenden Wertes wahrscheinlich ist oder nicht) darstellen. Letztere Option ist mit Vorsicht zu genießen. Erstens, weil sie möglicherweise keine zuverlässige Erkennungsmethode ist (z. B. führt eine Addition nicht unbedingt zu einem niedrigeren Wert). Zweitens, weil das Auftreten eines Überlaufs selbst in einigen Fällen ein undefiniertes Verhalten darstellen kann. In der Programmiersprache C führt ein Überlauf von Integer-Typen ohne Vorzeichen zu einem Umbruch, während ein Überlauf von Integer-Typen mit Vorzeichen ein undefiniertes Verhalten darstellt. Folglich kann ein C-Compiler davon ausgehen, dass der Programmierer sichergestellt hat, dass ein Überlauf mit Vorzeichen nicht auftreten kann, und kann daher jede Prüfung nach der Berechnung, die eine Überprüfung des Ergebnisses zur Erkennung des Überlaufs beinhaltet, stillschweigend optimieren, ohne dem Programmierer eine Warnung zu geben. Es ist daher ratsam, Prüfungen immer vor und nicht nach Berechnungen zu implementieren.

Explizite WeitergabeBearbeiten

Wenn ein Wert zu groß ist, um gespeichert zu werden, kann ihm ein spezieller Wert zugewiesen werden, der anzeigt, dass ein Überlauf aufgetreten ist, und dann alle nachfolgenden Operationen diesen Flag-Wert zurückgeben. Solche Werte werden manchmal als NaN bezeichnet, was für „not a number“ steht. Dies ist nützlich, damit das Problem einmal am Ende einer langen Berechnung geprüft werden kann und nicht nach jedem Schritt. Dies wird oft von Fließkommahardware, den sogenannten FPUs, unterstützt.

ProgrammiersprachenunterstützungBearbeiten

Programmiersprachen implementieren verschiedene Methoden zur Abschwächung eines versehentlichen Überlaufs: Ada, Seed7 (und bestimmte Varianten funktionaler Sprachen) lösen bei einem Überlauf eine Ausnahmebedingung aus, während Python (seit 2.4) die interne Darstellung der Zahl nahtlos an ihr Wachstum anpasst und sie schließlich als long darstellt – deren Fähigkeit nur durch den verfügbaren Speicher begrenzt ist.

In Sprachen mit nativer Unterstützung für Arithmetik mit beliebiger Genauigkeit und Typsicherheit (wie Python, Smalltalk oder Common Lisp) werden Zahlen bei Überläufen automatisch vergrößert oder Ausnahmen ausgelöst (Bedingungen signalisiert), wenn eine Bereichsbeschränkung besteht. Die Verwendung solcher Sprachen kann daher hilfreich sein, um dieses Problem zu entschärfen. In einigen dieser Sprachen sind jedoch immer noch Situationen möglich, in denen ein Integer-Überlauf auftreten kann. Ein Beispiel ist die explizite Optimierung eines Codepfads, der vom Profiler als Engpass angesehen wird. Im Fall von Common Lisp ist dies möglich, indem eine explizite Deklaration verwendet wird, um eine Variable auf ein Wort in Maschinengröße (fixnum) zu typisieren und die Typsicherheitsstufe für einen bestimmten Codeblock auf Null zu senken.

Im krassen Gegensatz zu älteren Sprachen wie C bieten einige neuere Sprachen, wie z. B. Rust, eingebaute Funktionen, die eine einfache Erkennung und die Entscheidung des Benutzers darüber ermöglichen, wie ein Überlauf von Fall zu Fall behandelt werden soll. In Rust fehlt diese Flexibilität natürlich bei der Verwendung grundlegender mathematischer Operatoren, aber der Benutzer kann alternativ Berechnungen über eine Reihe von Methoden durchführen, die von jedem der primitiven Ganzzahltypen bereitgestellt werden. Diese Methoden geben dem Benutzer die Wahl zwischen einer „geprüften“ (oder „überlaufenden“) Operation (die über den Rückgabetyp anzeigt, ob ein Überlauf stattgefunden hat oder nicht), einer „ungeprüften“ Operation, einer Operation, die einen Umbruch durchführt, oder einer Operation, die eine Sättigung an den numerischen Grenzen durchführt.

Gesättigte ArithmetikBearbeiten

In der Computergrafik oder Signalverarbeitung ist es typisch, mit Daten zu arbeiten, die von 0 bis 1 oder von -1 bis 1 reichen. Nehmen wir zum Beispiel ein Graustufenbild, bei dem 0 für Schwarz, 1 für Weiß und die Werte dazwischen für Grautöne stehen. Eine Operation, die man vielleicht unterstützen möchte, ist die Aufhellung des Bildes durch Multiplikation jedes Pixels mit einer Konstante. Die gesättigte Arithmetik erlaubt es, jedes Pixel blind mit dieser Konstante zu multiplizieren, ohne sich Gedanken über einen Überlauf zu machen, indem man sich einfach an ein vernünftiges Ergebnis hält, dass alle Pixel, die größer als 1 sind (d.h. „heller als weiß“), einfach weiß werden und alle Werte, die „dunkler als schwarz“ sind, einfach schwarz werden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.