淺析C語言編程中的數(shù)組越界問題
因?yàn)镃語言不檢查數(shù)組越界,而數(shù)組又是我們經(jīng)常用的數(shù)據(jù)結(jié)構(gòu)之一,所以程序中經(jīng)常會遇到數(shù)組越界的情況,并且后果輕者讀寫數(shù)據(jù)不對,重者程序crash。下面我們來分析一下數(shù)組越界的情況:
1) 堆中的數(shù)組越界
因?yàn)槎咽俏覀冏约悍峙涞?,如果越界,那么會把堆中其他空間的數(shù)據(jù)給寫掉,或讀取了其他空間的數(shù)據(jù),這樣就會導(dǎo)致其他變量的數(shù)據(jù)變得不對,如果是一個(gè)指針的話,那么有可能會引起crash
2) 棧中的數(shù)組越界
因?yàn)闂J窍蛳略鲩L的,在進(jìn)入一個(gè)函數(shù)之前,會先把參數(shù)和下一步要執(zhí)行的指令地址(通過call實(shí)現(xiàn))壓棧,在函數(shù)的入口會把ebp壓棧,并把esp賦值給ebp,在函數(shù)返回的時(shí)候,將ebp值賦給esp,pop先前棧內(nèi)的上級函數(shù)棧的基地址給ebp,恢復(fù)原?;?,然后把調(diào)用函數(shù)之前的壓入棧的指令地址pop出來(通過ret實(shí)現(xiàn))。
棧是由高往低增長的,而數(shù)組的存儲是由低位往高位存的 ,如果越界的話,會把當(dāng)前函數(shù)的ebp和下一跳的指令地址覆蓋掉,如果覆蓋了當(dāng)前函數(shù)的ebp,那么在恢復(fù)的時(shí)候esp就不能指向正確的地方,從而導(dǎo)致未可知的情況,如果下一跳的地址也被覆蓋掉,那么肯定會導(dǎo)致crash。
-------------------------
壓入的參數(shù)和函數(shù)指針
-------------------------
aa[4]
aa[3]
合法的數(shù)組空間 aa[2]
aa[1]
aa[0]
-------------------------
###sta.c###
#include <stdio.h>
void f(int ai)
{
int aa[5]={1,2,3};
int i = 1;
for (i=0;i<10;i++)
aa[i]=i;
printf("f()/n");
}
void main()
{
f(3);
printf("ok/n");
}
###sta.s###
.file "sta.c" ;說明匯編的源程序
.section .rodata ;說明以下是只讀數(shù)據(jù)區(qū)
.LC0:
.string "f()" ;"f()" 的類型是string,地址為LC0
.text ;代碼段開始
.globl f ;f為全局可訪問
.type f, @function ; f是函數(shù)
f:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl $0, -24(%ebp)
movl $0, -20(%ebp)
movl $0, -16(%ebp)
movl $0, -12(%ebp)
movl $0, -8(%ebp)
movl $1, -24(%ebp)
movl $2, -20(%ebp)
movl $3, -16(%ebp)
movl $1, -4(%ebp)
movl $0, -4(%ebp)
jmp .L2
.L3:
movl -4(%ebp), %edx
movl -4(%ebp), %eax
movl %eax, -24(%ebp,%edx,4)
addl $1, -4(%ebp)
.L2:
cmpl $9, -4(%ebp)
jle .L3
movl $.LC0, (%esp)
call puts
leave
ret
.size f, .-f ;用以計(jì)算函數(shù)f的大小
.section .rodata
.LC1:
.string "ok"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $4, %esp
movl $3, (%esp)
call f
movl $.LC1, (%esp)
call puts
addl $4, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 20070115 (SUSE Linux)" ;說明是用什么工具編譯的
.section .note.GNU-stack,"",@progbits
從main函數(shù)開始壓入f函數(shù)的參數(shù)開始,堆棧的調(diào)用情況如下
圖1 壓入?yún)?shù)
圖二 通過call 命令壓入下一跳地址 IP
圖三 函數(shù)f 通過pushl %ebp 把 ebp保存起來
圖四 函數(shù) f 通過movl %esp, %ebp讓ebp指向esp,這樣esp就可以進(jìn)行修改,在函數(shù)返回的時(shí)候用ebp的值對esp進(jìn)行恢復(fù)
圖五 函數(shù) f 通過subl $40, %esp 給函數(shù)的局部變量預(yù)留空間
圖六 int數(shù)組 aa[5]占用了20個(gè)字節(jié)的空間,然后 int i占用了4個(gè)字節(jié)的空間(緊鄰著之前壓入棧的%ebp)
故,如果aa[5]進(jìn)行賦值,則會把 i 的值覆蓋掉,
如果對aa[6]進(jìn)行賦值,則會把 棧中的 %ebp 覆蓋掉,那么在函數(shù) f 返回的時(shí)候則不能對ebp進(jìn)行恢復(fù),即main函數(shù)的ebp變成了我們覆蓋掉的值,程序不知道會發(fā)生什么事情,但因?yàn)槲覀兊某绦蚪酉聛頉]有調(diào)用棧中的內(nèi)容,故還是可以運(yùn)行的。
如果對aa[7]進(jìn)行賦值,則會把棧中的 %IP 覆蓋掉,在函數(shù) f 返回的時(shí)候就不能正確地找到下一跳的地址,會crash;
上一篇:深入解讀C語言中的符號常量EOF
欄 目:C語言
下一篇:C語言科學(xué)計(jì)算入門之矩陣乘法的相關(guān)計(jì)算
本文標(biāo)題:淺析C語言編程中的數(shù)組越界問題
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/2630.html
您可能感興趣的文章
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
- 01-10如何尋找數(shù)組中的第二大數(shù)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲方式詳解
- 01-10深入探討C語言中局部變量與全局變量在內(nèi)存中的存放位置
- 01-10深入解析C中的數(shù)值與真假
- 01-10探討:程序在內(nèi)存中的分配(常量,局部變量,全局變量,程序代碼)問
- 01-10基于linux下C開發(fā)中的幾點(diǎn)技術(shù)經(jīng)驗(yàn)總結(jié)
- 01-10淺析Linux下精確控制時(shí)間的函數(shù)


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10delphi制作wav文件的方法
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 08-05織夢dedecms什么時(shí)候用欄目交叉功能?
- 08-05DEDE織夢data目錄下的sessions文件夾有什


