邊界檢查

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

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

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

各編程語言的應用情況

在目前常見的編程語言中,強制進行邊界檢查的有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.