邊界檢查

邊界檢查程式設計中是指在使用某變數前,檢查該變數的值是否處在指定的範圍之內。最常見的是陣列的下標檢查,防止下標超出陣列範圍,覆蓋、運行其他堆疊位址資料。

若是變數超過範圍,而邊界檢查沒檢查到發,有可能是程式出現異常並終止執行,但也可能出現其他現象。

由於每次都進行邊界檢查非常耗時,而且有些代碼確定不會出現越界問題,所以這個操作並不總是需要被執行。一些現代編譯器中有稱為選擇性邊界檢查的技術,可以略去一些常見的不需要的邊界檢查,從而提高程式的效能。

各程式語言的應用情況

在目前常見的程式語言中,強制進行邊界檢查的有C#AdaHaskellJavaJavaScriptLispPHPPythonRubyVisual Basic。其中C#同時支援「unsafe塊」(不安全代碼塊),即一段暫時關閉邊界檢查、啟用指標以提高效率的代碼塊。這個功能常被用於加速一小段不可能出現越界問題的代碼的執行速度,而不至於破壞整個程式的安全性。除了這些語言,D語言OCaml也支援自動邊界檢查,但是允許使用者通過編譯器的一個開關選項來選擇是否啟用該功能。

 
差一錯誤,又稱「柵欄錯誤」:一個柵欄被一些柱子分割成10段,柱子的根數應該是11根,而不是10根。

然而,有一些程式語言(比如C語言)為了提高速度,從來都不會自動進行邊界檢查,這經常導致差一錯誤(見右圖)和緩衝區溢位的發生。許多程式設計師認為這些語言為了速度所付出的代價太大了。在1980年圖靈獎講座上,東尼·霍爾講述了他設計包含邊界檢查的ALGOL 60語言時的經歷[1]

範圍檢查

範圍檢查經常被用於確保某個數字處在一個特定的範圍之內。通常在訪問陣列的時候會進行該檢查,因為當陣列下標越界的時候,資料會被寫入其它變數的空間,甚至會覆蓋壓棧的暫存器數值。這樣一來,程式可能會崩潰,或者是導致一些安全漏洞的產生(見緩衝區溢位)。在Java中,Java虛擬機器將在嘗試訪問陣列中的元素的時候,自動的進行陣列邊界檢查,並且在下標越界的時候引發異常[2]

範圍檢查的另一個常見用途是在兩種資料類型相互轉換的時候。在構建在.NET Framework上的語言中,超出範圍的強制轉換將引發InvalidCastException類型的異常。[3]

比如將一個32位元有符號整數[錨點失效]類型的變數強制轉換到一個16位元有符號整數[錨點失效]類型的變數之前,會檢查這個變數的值是否在-32768~+32767之間(16位元有符號整數可以表示的整數範圍),而不是諸如32768之類的無法表示的數字。

陣列下標檢查

陣列下標檢查是指在程式中,所有陣列下標的表達式的結果在真正被用來訪問某一個特定的元素之前,先把它的值和定義陣列時給出的陣列上界和下界進行比較。如果一個下標超出了預期的範圍時,那麼就引發一個錯誤來阻止進一步的訪問。(例如:.NET Framework中的IndexOutOfRangeException[4]和ArgumentOutOfRangeException[5]類型異常

比如在訪問一個下標範圍是0~9的陣列前檢查下標是否也在0~9內,而不是如25之類的越過陣列結尾的下標。

除了軟體實現的下標檢查之外,VAX架構的電腦擁有一條INDEX組譯指令,可以用來檢查陣列的下標是否越界,可以至多提供6個任意VAX編址的位址。B6500和一些相似的伯勒斯電腦則以硬體進行邊界檢查,無論是採用什麼語言撰寫的程式。[6]

資料驗證

在資料集合資料品質範疇中,邊界檢查表示檢查一個並不總是錯誤的資料。比如,一個成年人的身高應該處在0到3米之間、利用率應該在0到1之間等。

參見

參考

  1. ^ The Emperor’s Old Clothes」, The 1980 ACM Turing Award Lecture, CACM volume 24 number 2, February 1981, pp 75–83.
  2. ^ 存档副本. [2011-11-10]. (原始內容存檔於2011-11-20). 
  3. ^ 存档副本. [2011-11-10]. (原始內容存檔於2016-03-28). 
  4. ^ 存档副本. [2011-11-10]. (原始內容存檔於2017-01-15). 
  5. ^ http://msdn.microsoft.com/library/zh-cn/system.collections.arraylist.item.aspx
  6. ^ Adar Nir, Grosman Rotem. VAX-11 Assembler and Simulator. Technion, Israel Institute of Technology.: p.42. [2011-11-10]. (原始內容 (pdf)存檔於2020-02-22) (英語). A subscript range trap is an exception indicating that the last instruction was an INDEX instruction with the subscript operand is lower than the low operand orgreater than the high operand.