因为C语言不检查数组越界,而数组又是我们经常用的数据结构之一,所以程序中经常会遇到数组越界的情况,并且后果轻者读写数据不对,重者程序crash。下面我们来分析一下数组越界的情况:

1) 堆中的数组越界

因为堆是我们自己分配的,如果越界,那么会把堆中其他空间的数据给写掉,或读取了其他空间的数据,这样就会导致其他变量的数据变得不对,如果是一个指针的话,那么有可能会引起crash

2) 栈中的数组越界

因为栈是向下增长的,在进入一个函数之前,会先把参数和下一步要执行的指令地址(通过call实现)压栈,在函数的入口会把ebp压栈,并把esp赋值给ebp,在函数返回的时候,将ebp值赋给esp,pop先前栈内的上级函数栈的基地址给ebp,恢复原栈基址,然后把调用函数之前的压入栈的指令地址pop出来(通过ret实现)。

栈是由高往低增长的,而数组的存储是由低位往高位存的 ,如果越界的话,会把当前函数的ebp和下一跳的指令地址覆盖掉,如果覆盖了当前函数的ebp,那么在恢复的时候esp就不能指向正确的地方,从而导致未可知的情况,如果下一跳的地址也被覆盖掉,那么肯定会导致crash。

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

压入的参数和函数指针

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

aa[4]

aa[3]

合法的数组空间   aa[2]

aa[1]

aa[0]

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

###sta.c###

#include

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 ;说明以下是只读数据区

.LC0:

.string "f()" ;"f()" 的类型是string,地址为LC0

.text ;代码段开始

.globl f ;f为全局可访问

.type f, @function ; f是函数

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 ;用以计算函数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函数开始压入f函数的参数开始,堆栈的调用情况如下

图1  压入参数

图二  通过call 命令压入下一跳地址 IP

图三  函数f 通过pushl   %ebp 把 ebp保存起来

图四  函数 f 通过movl    %esp, %ebp让ebp指向esp,这样esp就可以进行修改,在函数返回的时候用ebp的值对esp进行恢复

图五  函数 f 通过subl    $40, %esp 给函数的局部变量预留空间

图六  int数组 aa[5]占用了20个字节的空间,然后 int i占用了4个字节的空间(紧邻着之前压入栈的%ebp)

故,如果aa[5]进行赋值,则会把 i 的值覆盖掉,

如果对aa[6]进行赋值,则会把 栈中的 %ebp 覆盖掉,那么在函数 f 返回的时候则不能对ebp进行恢复,即main函数的ebp变成了我们覆盖掉的值,程序不知道会发生什么事情,但因为我们的程序接下来没有调用栈中的内容,故还是可以运行的。

如果对aa[7]进行赋值,则会把栈中的 %IP 覆盖掉,在函数 f 返回的时候就不能正确地找到下一跳的地址,会crash;

c语言程序越界,浅析C语言编程中的数组越界问题相关推荐

  1. ios 数组越界奔溃库_iOS中防止数组越界之后发生崩溃

    在iOS开发中有时会遇到数组越界的问题,从而导致程序崩溃.为了防止程序崩溃,我们就要对数组越界进行处理.通过上网查资料,发现可以通过为数组写一个分类来解决此问题. 基本思路:为NSArray写一个防止 ...

  2. c语言数组的存储与越界,C语言中的数组越界问题解决方法

    1.数组越界,是指访问了超出数组定义的内容. 实例: int  a[2]; 数组a定义了2个元素! a[0],a[1]:没有越界. a[2]:越界了! 对不对? 2.计算机全部的内存,其地址是从小到大 ...

  3. 8255a初始化c语言程序,8255A的c语言程序.doc

    8255A的c语言程序 8255A的c语言程序 [实例24]用8243扩展I/O端口 #include sbit ContrBit0=P1^0; sbit ContrBit1=P1^1; sbit C ...

  4. 数控机床需要c语言程序吗,数控机床的编程有几种方法?

    数控钻孔机床的编程分为手动编程和自动编程 1.手动编程 手动编程是指手动零件加工编程的全过程,即从零件图的分析,确定加工过程,数值计算,编制零件加工程序清单,输入到数控装置直至程序检查.一般为几何形状 ...

  5. 编写一个分奇偶的c语言程序,程序设计入门——C语言 第3周编程练习 1 奇偶个数(5分)...

    1 题目内容: 你的程序要读入一系列正整数数据,输入-1表示输入结束,-1本身不是输入的数据.程序输出读到的数据中的奇数和偶数的个数. 输入格式: 一系列正整数,整数的范围是(0,100000).如果 ...

  6. 大猛网赚编程之从易语言走向c,浅析易语言网赚应用心得

    以下就是关于易语言网赚应用学习心得内容: 最开始学习易语言,还是因为混互联网比较方便,当年网赚很流行,很多东西希望能够软件化自动化,所以一气之下就学了. 任何一种编程语言都是博大精深的,就算是易语言也 ...

  7. c语言程序链接过程,C语言简明教程(二):C程序编译链接过程和实例对照详解...

    不像高级编程语言,在C语言开发中,了解其编译链接过程显得相对重要,因为C语言是较为底层的语言,很多时候我们调试C程序或者解决其它问题都可能会涉及到C编译链接的相关知识,例如编译动态库或者静态库.下面我 ...

  8. c语言程序的引言,C语言程序设计-第1章-引言

    <C语言程序设计-第1章-引言>由会员分享,可在线阅读,更多相关<C语言程序设计-第1章-引言(80页珍藏版)>请在人人文库网上搜索. 1.c语言编程,2,1 .你为什么学这门 ...

  9. c语言程序编写字体,c语言程序设计练习题

    c语言程序设计练习题 篇一:c语言程序设计基础单元总结与练习题及答案 <C语言程序设计>单元总结与练习题 答 案 单元一 程序设计宏观认识 单元总结提升 本单元中,核心内容有C语言程序框架 ...

最新文章

  1. Dubbo开源现状与未来规划
  2. 如何编译和运行C++程序
  3. 我摊牌了,这就是我的生活
  4. SAP Fiori Launchpad tile点击之后的跳转链接是如何解析出来的
  5. JeeWx 捷微二代微信活动平台1.0发布!活动插件持续开源更新!
  6. 熊猫多模式站群 模型handlers流程图
  7. 搞不定的C语言--static的作用
  8. html模态窗口调试,在模态窗口中显示HTML标记
  9. CTS(11)---android自动化测试CTS源码分析之一
  10. 【highlight】highlight 动态添加代码,样式失效
  11. 在Zabbix中添加交换机端口监控
  12. python描述器descriptor_python装饰器decorator、描述器descriptor
  13. android连接程序,android程序如何连接真机进行测试
  14. 使用JS打开word在线编辑,直接编辑在线doc文件
  15. java-抽奖小程序
  16. 一键adb关闭系统更新 坚果手机_华为手机通过ADB永久关闭系统更新
  17. 远程桌面连接笔记本,wifi自动断开导致远程断开解决方法
  18. ios html 编码转换,IOS中编码转换方法(转)
  19. 如何用光盘映像文件重装服务器系统,光盘映像文件怎么安装,小编教你光盘映像文件怎么安装系统...
  20. 牛客-Mysql实战-按热度排序(前20)

热门文章

  1. 数学学习与研究杂志数学学习与研究杂志社《数学学习与研究》杂志社2023年第2期目录
  2. Java查漏补缺之Java8新特性
  3. mysql2014 三合一_SQL Server 2014 全系列 MSDN iso镜像
  4. centos7 pe系统安装_如何用U盘安装CentOS7系统
  5. Android--刷机与adb
  6. 求无向图的连通分量或有向图的强连通分量—tarjan()ccf高速公路
  7. IntelliJ Idea 常用10款插件
  8. spring实战笔记_第4章
  9. feature map
  10. crtsiii型无砟轨道板_北京雄安城际全线轨道贯通:全程设5座车站,1小时通勤,“刷脸”进站...