整数のオーバーフロー

様々なプログラミング言語における整数のオーバーフロー処理
言語 符号なし整数 符号あり整数
Ada modulo 型のモジュラス raise Constraint_Error
C/C++ modulo power of two undefined behavior
C# modulo power of 2 in unchecked context; チェックされたコンテキストでは System.OverflowException が発生
Java N/A modulo power of two
JavaScript all numbers are double-> JavaScript modulo power of 2
Java N/A
MATLAB Builtin integers saturateを除く高精度浮動小数点数です。 固定小数点点整数をラップまたは飽和に設定可能
Python 2 N/A ロングタイプに変換する。 (bigint)
Seed7 N/A raise OVERFLOW_ERROR
Scheme N/A bigNumに変換
Simulink ラップまたは飽和に設定可能
Smalltalk N/A convert to LargeInteger
Swift 特別なオーバーフロー演算子を使用しないとエラーになります。

DetectionEdit

ランタイムオーバーフロー検出実装 UBSan は C コンパイラで利用できます。

Java8ではオーバーロードされたメソッドがあり、たとえば Math.addExact(int, int) のようにオーバーフローした場合に ArithmeticException がスローされます。

CERT (Computer Emergency Response Team) は、実行時エラー処理を使用して C/C++ で整数のオーバーフローと切り捨てを排除する、ほぼ自動のメカニズムである As-if Infinitely Ranged (AIR) 整数モデルを開発しました。

AvoidanceEdit

その中に計算および格納できるすべての値を含むために十分に大きいデータ型の変数を割り当てることによって、オーバーフローは常に避けられる可能があります。 プログラミング言語や環境で利用可能な領域や固定データ型が限られていて、防御的に余裕のある大きさの変数を割り当てることができない場合でも、演算を慎重に順序付け、オペランドを事前にチェックすることによって、結果が格納可能なサイズより大きくならないことを先験的に保証できることが多い。 静的解析ツール、形式検証、および契約による設計技法を使用して、オーバーフローが偶然に発生しないことをより確実かつ堅牢に保証することができます。 たとえば、ユーザー入力から計算された重要な結果がオーバーフローした場合、プログラムは停止し、入力を拒否し、おそらくユーザーに別の入力を促すことができます。 このプロセスはすべて自動化できます。整数のオーバーフローに対するハンドラを自動的に合成することが可能で、ハンドラはたとえば、クリーンな終了となります。このため、2バイト幅の2つの数値を、まず下位バイトを加算し、次に上位バイトを加算するというステップのバイト加算だけで加算することが可能ですが、下位バイトから繰り出す必要がある場合は、バイト加算の算術オーバーフローとなり、上位バイトの和を検出してインクリメントする必要が出てきます。

計算のオーバーフローの可能性を処理する場合、実際の計算の前にチェックを行うか(オーバーフローが発生するかどうかを判断する)、計算の後に行うか(結果の値に基づいて発生しそうかどうかを検討する)の選択を迫られることがあります。 後者の選択には注意が必要です。 第一に、信頼できる検出方法とは限らないからである(例えば、加算が必ずしも低い値にラップされるとは限らない)。 第二に、オーバーフローの発生自体が未定義の動作である場合があるためです。 C言語では、符号なし整数型のオーバーフローはラップされますが、符号付き整数型のオーバーフローは未定義の動作です。そのため、Cコンパイラは、プログラマが符号付きオーバーフローが起こり得ないことを保証していると自由に判断し、プログラマに警告を与えずに計算結果のチェックに続くすべてのチェックを黙々と最適化し、検出することができるようになっています。

Explicit propagationEdit

if a value is too large to be stored it can be assigned a special value indicating that overflow has occurred and then have all successive operation return this flag value. このような値は、「数字ではない」という意味でNaNと呼ばれることがあります。 これは、各ステップの後ではなく、長い計算の最後に一度だけ問題を確認するのに便利である。 これはFPUと呼ばれる浮動小数点ハードウェアでよくサポートされている。

Programming language supportEdit

プログラミング言語は偶発的なオーバーフローに対して様々な緩和策を実装している。 Ada、Seed7 (および特定の関数型言語) はオーバーフロー時に例外条件を発生させ、一方 Python (2.4 以降) は数の増加に合わせて内部表現をシームレスに変換し、最終的に long として表現します (この能力は使用可能なメモリによってのみ制限されます)。

Arbitrary-precision arithmetic と型安全性をネイティブにサポートする言語 (Python, Smalltalk や Common Lisp など) では、オーバーフローが発生すると数値は自動的に大きなサイズに昇格し、範囲制約が存在すると例外がスロー (条件がシグナル) されています。 そのため、このような言語を使用することは、この問題を軽減するのに役立つと思われる。 しかし、このような言語でも整数オーバーフローが発生する可能性がある場合がある。 例えば、プロファイラがボトルネックと判断したコードパスの明示的な最適化などである。 Common Lisp の場合、これは、明示的な宣言を使用して、変数をマシン サイズのワード (fixnum) に型付けし、特定のコード ブロックの型安全レベルをゼロに下げることで可能です。

C などの古い言語とはまったく異なり、たとえば Rust などいくつかの新しい言語では、オーバーフローがケースバイケースで処理されるべき方法を簡単に検出しユーザーが選択できるような組み込み機能が提供されています。 Rustでは、基本的な数学演算子にはそのような柔軟性はないが、代わりに、各整数プリミティブ型が提供する一連のメソッドによって計算を実行することができる。 これらのメソッドは、「checked」(または「overflowing」)演算(戻り値の型によってオーバーフローが発生したかどうかを示す)、「unchecked」演算、折り返し演算、または数値境界での飽和演算の実行の中からユーザーにいくつかの選択肢を提供する。 例えば、0が黒、1が白、その中間の値がグレーの濃淡を表すグレースケール画像を考えてみましょう。 このとき、各ピクセルに定数をかけて、画像を明るくすることができます。 飽和演算では、1 より大きいピクセル(つまり「白より明るい」)はすべて白になり、「黒より暗い」値はすべて黒になるという妥当な結果にこだわるだけで、オーバーフローの心配をせずに、やみくもにすべてのピクセルにこの定数を掛けることができます

コメントを残す

メールアドレスが公開されることはありません。