閱讀下面**,並分析導致其結果的原因(以下分析基於vs環境的除錯)
#include
#include
intmain()
;//擁有10個元素的整型陣列
for(i =
0; i <=
12; i++
)//迴圈13次,越界訪問
system
("pause");
return0;
}
分析:整型陣列arr有10個元素,for迴圈13次,導致陣列越界訪問。執行程式結果顯示如下如圖所示,「hello world」在螢幕迴圈列印,陷入死迴圈中。
基於visual studio 2013進行除錯,分析陣列越界為什麼會導致程式陷入死迴圈中。
i 從0加至9,迴圈10次,在螢幕上列印10次「hello world」,並將陣列arr中的全部內容置為0.
i 加至10和11時,越界訪問了arr[10]和arr[11],並將arr[10]和arr[11]置為0,當i加至12時將arr[12]也置為0,此時發現 i 也被置為0。
細心的讀者就可能會發現,在i加至10、11、12時arr[12]中的內容也隨之被改為10、11、12,即圖中綠色標記處。那麼問題又來了為什麼 i 的改變導致arr[12]的改變呢?
觀察 i 的位址和arr[12]的位址如下圖,i 的位址和arr[12]的位址均是 0x 00 dd fe ec ,這也就解釋了為什麼 i 的改變會導致arr[12]的改變。
這就能解釋清楚為什麼陣列越界會導致程式陷入死迴圈:
for迴圈迴圈13次(i 從0加至12),陣列arr下標0至9,當 i = 10、11、12 時,越界訪問陣列,因為 i 的位址和arr[12]的位址相同,是同一變數空間,當 i = 12 時,將arr[12] 置為0,也就是將 i 置為0,因此for迴圈中的條件2永遠成立,也就是說 i <=12 恆成立,所以程式陷入死迴圈中。
1.生命週期:變數的作用範圍,變數的建立到變數的銷毀之間的時間段。
2.記憶體:記憶體儲器的儲存量,乙個資料得占用一塊物理空間,邏輯的東西必須有物理的東西來支援。而儲存器在一般電腦上是:暫存器-> 快取->記憶體->硬碟。
3.棧區(stack):空間小,系統自動建立銷毀。生長方向是由高位址向低位址生長。
4.堆區(heap):程式設計師手動開闢,手動釋放,程式結束時可能由 os **。使用關鍵字malloc / new,free / delete對其開闢釋放空間,每個人電腦的空間都是有限的。生長方向是由低位址向高位址生長。
5.靜態區( static):內容在總個程式的生命週期內都存在,由編譯器在編譯的時候分配、儲存。
究其根源為什麼 i 和 arr[12] 是同一變數空間 區域性變數 i 和 arr 在棧區上被使用,因為棧區的生長方向是高位址向低位址生長,所以棧區是先使用高位址處的空間,後使用低位址處的空間,又因為陣列隨著下標的增長位址由低向高變化,當越界訪問適當時,就會訪問到變數 i ,執行arr[i]=0;後就會將 i 置為0,導致程式陷入死迴圈中。棧區的分布如圖所示。
修改:for迴圈中的迴圈條件為 i<=11 時,不會越界訪問到變數 i ,就不會陷入死迴圈中,系統會提示報錯資訊。
對比:以上是在vs2013上進行除錯和編譯的,在不同的編譯器死迴圈的位置可能不盡相同。在vc6.0中測試for(i=0;i<=10;i++)程式陷入死迴圈,在linux的gcc中測試for(i=0;i<=11;i++)程式陷入死迴圈。那麼在不同編譯器下的記憶體布局如下圖所示。
Linux 棧中陣列訪問越界導致死迴圈現象
最近在學習極客時間課程過程中碰到個挺有意思的關於陣列和linux 棧中增長方向的問題,特來與大家分享下。話不多說,先上 int main int argc,char ar for i 3 i return 0 很簡單。當使用gcc 搭配上 fno stack protector 禁用堆疊保護 選項進...
C語言中陣列越界導致死迴圈的測試
include 如何把這段 變成死迴圈,就像 c語言缺陷和陷阱 裡描述的那樣 經過測試發現,變數i的位址和a crazynum 的位址一樣,當執行 a crazynum 0 相當於i 0 所以死迴圈跑起來啦。測試環境 win7 32 dev c 4.9.9.2 c語言缺陷和陷阱 中的場景是編譯器按照...
HashMap之鍊錶導致死迴圈
描述 hashmap採用拉鍊法 陣列鍊錶 解決hash衝突,因為是鍊錶結構,那麼就很容易形成閉合的鏈路。在單執行緒情況下,只有乙個執行緒對hashmap的資料結構進行操作,是不可能產生閉合的迴路的。那就只有在多執行緒併發的情況下才會出現這種情況,那就是在put操作的時候,如果size nitialc...