一般狀況下在C語言中咱們定義一個大小爲5的數組是這樣的:html
int arr[5] = {1,2,3,4,5};
1,2,3,4,5
這五個數字對應的下標是0,1,2,3,4
,當咱們想訪問數組中第一個數字時,一般會使用arr[0]
的形式去訪問,可是,若是咱們使用arr[5]=6
來對超過數組大小的地方進行賦值,會發生什麼?
數組
編譯以後,發現編譯器並無報錯,也沒有警告,可是咱們知道,這裏其實已經發生了數組越界問題。
那咱們先來看一下不進行數組越界操做的時候反彙編是什麼樣的:
函數
再來看一下對數組進行越界操做的時候是什麼樣的:
code
對比以後發如今添加了一句arr[5]=6
以後,反彙編代碼這裏多出一句0040104B mov word ptr [ebp],6
,也就是6被存到內存地址爲[ebp]
的地方了。
參照上一篇文章,能夠知道[ebp]
是存放原ebp的地址,也就是函數執行第一步的push ebp
,一個函數在開始執行前,會將下一條指令的地址壓入棧中,位置是[ebp+4]
,這裏咱們注意到,arr[5]
的位置是[ebp]
,那麼[ebp+4]
的位置就是arr[6]
,存放在這裏的值在函數結束以後會被存放到EIP中當成下一條指令的地址,執行此處的指令。
那麼咱們要是在arr[6]
的位置換成另外一個函數的地址,那麼在這個函數結束後不就能夠自動調用另外一個函數了,因而將原來的代碼改爲這樣:htm
#include <stdio.h> void First(); void Hello(); int main(void) { First(); return 0; } void First() { int arr[5] = {1,2,3,4,5}; arr[6] = (int)Hello; } void Hello() { printf("Hello World!"); getchar(); }
這樣,根據咱們的構想,在主函數裏面調用了First函數,可是在First函數結束後,會調用Hello函數:
blog
這裏能夠看到返回地址被改爲了Hello函數的入口地址:
從上面就能夠看出數組越界的危害性。內存