天天看點

數組越界死循環問題(詳細,通俗,易懂)

首先我們來看一個程式:

#include<stdio.h>
int main()
{
	int i = 0;
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	for (i = 0; i <= 12; i++)
	{
		printf("王笙\n");
		arr[i] = 0;
	}
	return 0;
}
           

  這個程式放到編譯器中運作的話會造成死循環,那這時我們可能會想,數組的總元素是10,而循環語句中的i要循環到12才結束,那麼肯定會出現數組越界報錯啊,但為什麼會出現死循環而不是數組越界,并且這個語句為什麼會形成死循環呢?下面我來給大家解釋。

首先我們得先從棧開始講起(不知道什麼是棧的小夥伴可以自己去搜),我們平時建立的局部變量就放在棧中,而棧的使用規則從高位址向低位址使用的。并且單個數組元素在棧中的位址相對大小和下标大小相同,也就是說變量i和數組在棧中的位置關系如下圖所示。

高位址
                                                     i
                                                 arr[9]
                                                 arr[8]
                                                 arr[7]
                                                   6
                                                   5
                                                   4
                                                   3
                                                   2
                                                   1
低位址                                        0

那麼這就明了了,當數組越界後,i一直++,直到i=12時,此時arr[12]與i,他們倆的位址一樣,所代表的的記憶體空間一樣,可以說arr[12]就是i了,此時給arr[12]指派為0,也就是重新給i指派為0,那麼這個循環會重新開始,也就造成了死循環。

什麼?你說為什麼越界了不報錯,而還要++呢。啊~這........咳咳,老師說這個程式因為忙着死循環就顧不上報錯,估計他的意思是死循環可能占用了某些功能,或者壓榨了空間記憶體等等,系統一直處于死循環沒空報錯吧!

這個空間的相對位置,不是我随便舉個例子,而是在棧中他的确就是這麼存放的(vs2019環境下)。不同的環境可能相對位置有些出入,但大緻上就是這麼個原理,如果把i改為循環到11,那麼系統會出現越界報錯,因為下标12的位置是i變量,但他隻能循環到11,那麼這時就不會出現死循環,就會報錯了,當然如果改成循環到14,15,那麼肯定會死循環的,因為比12大啊!哈哈!

補充: 

      vc6.0環境下<=10就死循環了,gcc編譯器<=11就死循環了,vs2013環境下<=12 就死循環了。

debug版本的程式如果寫成上述代碼會出現這種問題,如果是release版本的程式則不會出現,因為系統會進行優化,一般情況下會使i變量的位址小于數組位址這樣就不會出現這樣的問題了。

繼續閱讀