コンピュータプログラミングにおいて、境界チェックとは、変数を使用する前に、その変数が何らかの範囲内にあるかどうかを検出するあらゆる方法を指します。これは通常、数値が指定された型に収まるかどうか(範囲チェック)、または配列のインデックスとして使用される変数が配列の範囲内にあるかどうか(インデックスチェック)を確認するために使用されます。境界チェックが失敗すると、通常は何らかの例外シグナルが発生します。
使用のたびに境界チェックを実行するのは時間がかかるため、必ずしも行われるとは限りません。境界チェックの排除は、不要な境界チェックを排除するコンパイラ最適化手法です。
範囲チェックは、数値がプログラムの動作に適した範囲内にあることを確認します。例えば、16ビット整数に代入しようとしている値が16ビット整数の容量内に収まっていることを確認する(つまり、オーバーフローが発生しないことを確認する)といった場合です。これは、データ型がプログラムの型システムに適していることを確認する型チェックとは若干異なります。範囲チェックの中には、より制限の厳しいものもあります。例えば、暦月の番号を保持する変数は、1から12までの範囲のみを受け入れるように宣言することができます。
Pythonの例:
def set_month ( month : int ): if month < 1 or month > 12 : raise ValueError ( "月は1から12の間である必要があります" )インデックスチェックとは、配列をインデックス指定するすべての式において、インデックス値が配列の定義時に設定された配列の境界値と比較され、インデックスが境界値を超えている場合は、何らかのエラーによって処理が中断されることを意味します。配列の境界外の値を読み取ったり、特に書き込んだりすると、プログラムが誤動作したりクラッシュしたり、セキュリティ上の脆弱性(バッファオーバーフローなど)を生じさせたりする可能性があるため、インデックスチェックは多くの高級言語に不可欠な機能となっています。
インデックスチェック機能を備えた初期のコンパイル型プログラミング言語には、ALGOL 60、ALGOL 68、Pascalなどがあり、 BASICのようなインタプリタ型プログラミング言語もあった。
C言語など多くのプログラミング言語は、速度向上のために自動境界チェックを行いません。しかし、このため、多くのオフバイワンエラーやバッファオーバーフローが見逃されてしまいます。多くのプログラマーは、これらの言語は高速実行のために多くのものを犠牲にしていると考えています。[ 1 ] 1980年のチューリング賞受賞講演で、CAR Hoareは境界チェック機能を備えた言語ALGOL 60の設計経験について次のように述べています。
この原則の結果として、添え字付き変数の添え字はすべて、実行時に配列の宣言された上限と下限の両方に対して必ずチェックされました。何年も後、本番環境での効率化のために、これらのチェックを無効にするオプションを提供するかどうかを顧客に尋ねました。すると、顧客は満場一致でそうしないよう強く求めました。添え字エラーが本番環境でどれほど頻繁に発生し、それを検出できないと壊滅的な結果を招くかを、顧客は既に知っていたからです。1980年になっても、言語設計者やユーザーがこの教訓を学んでいないことに、私は恐怖と憤りを感じています。まともな工学分野では、このような基本的な予防措置を怠ることは、とっくに法律違反とみなされていたはずです。
実行時チェックを強制する主流言語には、Ada、C#、Haskell、Java、JavaScript、Lisp、PHP、Python、Ruby、Rust、Visual Basicなどがあります。D言語とOCaml言語には、コンパイラスイッチで有効または無効にできる実行時境界チェックがあります。C ++では、実行時チェックは言語の一部ではなく、STLの一部であり、コンパイラスイッチ(_GLIBCXX_DEBUG=1または_LIBCPP_DEBUG=1)で有効になります。C#は、効率を高めるために(とりわけ)一時的に境界チェックを停止するコードセクションである、安全でない領域もサポートしています。これらは、プログラム全体の安全性を犠牲にすることなく、小さな時間制約のあるボトルネックを高速化するのに役立ちます。
JS ++プログラミング言語は、既存の型を使用してコンパイル時に配列のインデックスまたはマップのキーが範囲外かどうかを分析できます。既存の型は、インデックスまたはキーが範囲内か範囲外かを記述する名目上の型であり、コード生成をガイドします。既存の型はコンパイル時間に1ms のオーバーヘッドしか追加しないことが示されています。[ 2 ]
境界チェックによって追加される安全性は、チェックがソフトウェアで実行される場合は必然的にCPU 時間を消費しますが、チェックがハードウェアで実行できる場合は、実行時コストなしで「無料」で安全性を提供できます。ハードウェア境界チェックを備えた初期のシステムは、1974 年に発表されたICL 2900 シリーズメインフレームでした。 [ 3 ] VAXコンピュータには、配列インデックスチェック用の INDEX アセンブリ命令があり、これは 6 つのオペランドを受け取り、そのすべてで任意の VAXアドレッシング モードを使用できます。B6500 および同様のBurroughsコンピュータは、マシン コードを生成するためにコンパイルされたコンピュータ言語に関係なく、ハードウェアを介して境界チェックを実行しました。後期のCPUのごく一部には、境界チェック専用の命令があり、たとえばMotorola 68000シリーズの CHK2 命令などがあります。
配列やバッファへのアクセスを安全に保つために、x86 の組み込み仮想メモリ管理ユニットを使用する方法については、少なくとも 2005 年以降研究が進められてきました。[ 4 ] 2015 年に Intel は、 CPU レジスタとメモリ内のテーブルに境界を格納するIntel MPX拡張機能をSkylakeプロセッサ アーキテクチャで提供しました。2017 年初頭の時点では、少なくともGCC はMPX 拡張機能をサポートしています。