国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > C++ > 正文

淺析C語(yǔ)言編程中的數(shù)組越界問題

2020-05-23 14:13:37
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

這篇文章主要介紹了淺析C語(yǔ)言編程中的數(shù)組越界問題,通過(guò)內(nèi)存空間來(lái)討論其導(dǎo)致的程序崩潰問題,需要的朋友可以參考下

因?yàn)镃語(yǔ)言不檢查數(shù)組越界,而數(shù)組又是我們經(jīng)常用的數(shù)據(jù)結(jié)構(gòu)之一,所以程序中經(jīng)常會(huì)遇到數(shù)組越界的情況,并且后果輕者讀寫數(shù)據(jù)不對(duì),重者程序crash。下面我們來(lái)分析一下數(shù)組越界的情況:

1) 堆中的數(shù)組越界

因?yàn)槎咽俏覀冏约悍峙涞模绻浇纾敲磿?huì)把堆中其他空間的數(shù)據(jù)給寫掉,或讀取了其他空間的數(shù)據(jù),這樣就會(huì)導(dǎo)致其他變量的數(shù)據(jù)變得不對(duì),如果是一個(gè)指針的話,那么有可能會(huì)引起crash

2) 棧中的數(shù)組越界

因?yàn)闂J窍蛳略鲩L(zhǎng)的,在進(jìn)入一個(gè)函數(shù)之前,會(huì)先把參數(shù)和下一步要執(zhí)行的指令地址(通過(guò)call實(shí)現(xiàn))壓棧,在函數(shù)的入口會(huì)把ebp壓棧,并把esp賦值給ebp,在函數(shù)返回的時(shí)候,將ebp值賦給esp,pop先前棧內(nèi)的上級(jí)函數(shù)棧的基地址給ebp,恢復(fù)原棧基址,然后把調(diào)用函數(shù)之前的壓入棧的指令地址pop出來(lái)(通過(guò)ret實(shí)現(xiàn))。

棧是由高往低增長(zhǎng)的,而數(shù)組的存儲(chǔ)是由低位往高位存的 ,如果越界的話,會(huì)把當(dāng)前函數(shù)的ebp和下一跳的指令地址覆蓋掉,如果覆蓋了當(dāng)前函數(shù)的ebp,那么在恢復(fù)的時(shí)候esp就不能指向正確的地方,從而導(dǎo)致未可知的情況,如果下一跳的地址也被覆蓋掉,那么肯定會(huì)導(dǎo)致crash。

-------------------------

壓入的參數(shù)和函數(shù)指針

-------------------------

aa[4]

aa[3]

合法的數(shù)組空間 aa[2]

aa[1]

aa[0]

-------------------------

###sta.c###

 

 
  1. #include <stdio.h> 
  2.  
  3. void f(int ai) 
  4. int aa[5]={1,2,3}; 
  5. int i = 1; 
  6. for (i=0;i<10;i++) 
  7. aa[i]=i; 
  8. printf("f()/n"); 
  9.  
  10. void main() 
  11. f(3); 
  12. printf("ok/n"); 
  13.  
  14.  
  15.  
  16.  
  17.  
  18. ###sta.s### 
  19.  
  20. .file "sta.c" ;說(shuō)明匯編的源程序 
  21. .section .rodata ;說(shuō)明以下是只讀數(shù)據(jù)區(qū) 
  22. .LC0: 
  23. .string "f()" ;"f()" 的類型是string,地址為L(zhǎng)C0 
  24. .text ;代碼段開始 
  25. .globl f ;f為全局可訪問 
  26. .type f, @function ; f是函數(shù) 
  27. f: 
  28. pushl %ebp 
  29. movl %esp, %ebp 
  30. subl $40, %esp 
  31. movl $0, -24(%ebp) 
  32. movl $0, -20(%ebp) 
  33. movl $0, -16(%ebp) 
  34. movl $0, -12(%ebp) 
  35. movl $0, -8(%ebp) 
  36. movl $1, -24(%ebp) 
  37. movl $2, -20(%ebp) 
  38. movl $3, -16(%ebp) 
  39. movl $1, -4(%ebp) 
  40. movl $0, -4(%ebp) 
  41. jmp .L2 
  42. .L3: 
  43. movl -4(%ebp), %edx 
  44. movl -4(%ebp), %eax 
  45. movl %eax, -24(%ebp,%edx,4) 
  46. addl $1, -4(%ebp) 
  47. .L2: 
  48. cmpl $9, -4(%ebp) 
  49. jle .L3 
  50. movl $.LC0, (%esp) 
  51. call puts 
  52. leave 
  53. ret 
  54. .size f, .-f ;用以計(jì)算函數(shù)f的大小 
  55. .section .rodata 
  56. .LC1: 
  57. .string "ok" 
  58. .text 
  59. .globl main 
  60. .type main, @function 
  61. main: 
  62. leal 4(%esp), %ecx 
  63. andl $-16, %esp 
  64. pushl -4(%ecx) 
  65. pushl %ebp 
  66. movl %esp, %ebp 
  67. pushl %ecx 
  68. subl $4, %esp 
  69. movl $3, (%esp) 
  70. call f 
  71. movl $.LC1, (%esp) 
  72. call puts 
  73. addl $4, %esp 
  74. popl %ecx 
  75. popl %ebp 
  76. leal -4(%ecx), %esp 
  77. ret 
  78. .size main, .-main 
  79. .ident "GCC: (GNU) 4.1.2 20070115 (SUSE Linux)" ;說(shuō)明是用什么工具編譯的 
  80. .section .note.GNU-stack,"",@progbits 

從main函數(shù)開始?jí)喝雈函數(shù)的參數(shù)開始,堆棧的調(diào)用情況如下

淺析C語(yǔ)言編程中的數(shù)組越界問題

圖1 壓入?yún)?shù)

淺析C語(yǔ)言編程中的數(shù)組越界問題

圖二 通過(guò)call 命令壓入下一跳地址 IP

淺析C語(yǔ)言編程中的數(shù)組越界問題

圖三 函數(shù)f 通過(guò)pushl %ebp 把 ebp保存起來(lái)

淺析C語(yǔ)言編程中的數(shù)組越界問題

圖四 函數(shù) f 通過(guò)movl %esp, %ebp讓ebp指向esp,這樣esp就可以進(jìn)行修改,在函數(shù)返回的時(shí)候用ebp的值對(duì)esp進(jìn)行恢復(fù)

淺析C語(yǔ)言編程中的數(shù)組越界問題

圖五 函數(shù) f 通過(guò)subl $40, %esp 給函數(shù)的局部變量預(yù)留空間

淺析C語(yǔ)言編程中的數(shù)組越界問題

圖六 int數(shù)組 aa[5]占用了20個(gè)字節(jié)的空間,然后 int i占用了4個(gè)字節(jié)的空間(緊鄰著之前壓入棧的%ebp)

故,如果aa[5]進(jìn)行賦值,則會(huì)把 i 的值覆蓋掉,

如果對(duì)aa[6]進(jìn)行賦值,則會(huì)把 棧中的 %ebp 覆蓋掉,那么在函數(shù) f 返回的時(shí)候則不能對(duì)ebp進(jìn)行恢復(fù),即main函數(shù)的ebp變成了我們覆蓋掉的值,程序不知道會(huì)發(fā)生什么事情,但因?yàn)槲覀兊某绦蚪酉聛?lái)沒有調(diào)用棧中的內(nèi)容,故還是可以運(yùn)行的。

如果對(duì)aa[7]進(jìn)行賦值,則會(huì)把棧中的 %IP 覆蓋掉,在函數(shù) f 返回的時(shí)候就不能正確地找到下一跳的地址,會(huì)crash;


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 南投市| 岗巴县| 息烽县| 邻水| 西宁市| 宜良县| 比如县| 皮山县| 乐清市| 微博| 揭阳市| 邯郸市| 平度市| 乐昌市| 富民县| 淳安县| 宜兴市| 屯留县| 昌图县| 广灵县| 武威市| 富源县| 襄汾县| 奉节县| 冀州市| 崇左市| 南开区| 阿图什市| 抚州市| 清水县| 阿巴嘎旗| 奉贤区| 福鼎市| 甘孜| 克山县| 苏尼特左旗| 抚州市| 琼中| 广水市| 峨边| 台湾省|