C语言中的数组越界

C语言第十四课:操作符详解(上)——算数、移位、位、赋值操作符 我们在前面几篇文章中对井字棋和扫雷两个阶段性练习进行了详细的练习讲解,想必各位小伙伴们对于前面学到的知识也能较为充分的掌握了。从本文开始,我们将继续进行下一部分关于操作符的学习。 阅读详情

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

结合我的另外一篇文章 C语言的内存管理 http://blog.youkuaiyun.com/wind19/archive/2010/10/25/5964090.aspx

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

 

 

 

对于汇编代码中

leave                   ; 将ebp值赋给esp,pop先前栈内的上级函数栈的基地址给ebp,恢复原栈基址
ret                     ; main函数返回,回到上级调用,隐含了pop %eip操作,返回值由%eax带回

 

推荐文章 http://bbs.bccn.net/thread-106533-1-1.html

 

C语言中关于数组越界问题分析 在C语言中,数组越界是指对数组元素的访问超出了数组的合法索引范围。这是一个常见的编程错误,可能导致程序崩溃、产生未定义的行为或安全漏洞。 阅读详情

相关推荐

数组越界:C语言中的未定义行为

本文探讨了C语言中的数组越界问题。数组越界指访问超出数组合法范围的元素,会导致未定义行为,如程序崩溃、数据损坏或安全漏洞。示例代码展示了越界访问如何输出随机值。为避免这些问题,建议进行索引检查、使用安全函数、借助静态分析工具和动态调试。理解并防范数组越界是保证程序安全性和可靠性的关键技能。

m0_62153576的博客 62

数组越界

平时打题的时候,有时找一个bug找半天,就很难顶。 刚学数组那会儿,经常会看到数组越界四个字,当时我也是一脸懵逼 ,现在终于有时间来抓一下这条虫了。 定义:所谓数组越界,就是指数组下标变量的取值超过了初始定义时的大小,导致对数组元素的访问出现在数组的范围之外。 数组下标的取值范围只能预先推断一个值来确定数组的维数,作为秃头程序猿的我们,就得学会检验数组的边界啦。 一般情况下,数组的越界包括两种:数组下标取值越界与指向数组的指针的指向范围越界。 第一种:数组下标取值越界 意思就是访问数组的时候,下标的取值不在

SG_teresa's blog 1万+

论文浅读之PIP-Net: Patch-Based Intuitive Prototypes for Interpretable Image Classification

这篇文章的主要贡献包括:1 提出了一种新型的可解释图像分类模型PIP-Net,它基于原型部分学习可解释的原型,实现内置解释性。2 PIP-Net采用自监督学习的新正则化方法,学习原型之间的相似性,使得 latent 空间中的相似性能更好地与人类视觉感知相一致,从而减小了所谓的语义差距。3 PIP-Net可解释为一个稀疏的打分表,它可以检测图像是否属于任何类,或是否属于多个类。它也可以对OOD数据进行分类并说“我没有看到过这个”。

qq_49370210的博客 1791

数组越界及其避免方法,C语言数组越界详解

关注、星标公众号,直达精彩内容ID:技术让梦想更伟大作者:李肖遥所谓的数组越界,简单地讲就是指数组下标变量的取值超过了初始定义时的大小,导致对数组元素的访问出现在数组的范围之外,这类错误...

李肖遥的专栏 1万+

保姆级教程:Synology NAS共享文件夹从创建到权限设置的完整流程

本文提供了一份详尽的Synology NAS共享文件夹创建与权限设置指南。重点讲解了如何将NAS接入企业AD域,并利用域管理员账户进行集中身份验证和权限管理。文章从基础概念、域环境配置、文件夹创建、精细化权限分配到客户端访问与维护,完整覆盖了构建安全高效企业级文件共享空间的全流程,旨在帮助管理员实现便捷的团队协作与数据安全管理。

u9v0w的博客 556

修改注册表导致开机时电脑显示“无法登陆到你的账户”的问题解决方案

1.问题描述:开机电脑显示“无法登陆到你的账户:通常可以通过从你的账户注销,然后重新登陆来解决问题,如果不立即注销,你创建的任何文件或进行的任何更改都将会丢失。” 2.问题原因:想要修改cmd中的用户名(红色部分),修改了注册表,重启时出现问题。 3.问题解决: win+R输入cmd,确定进入注册表界面,将下面的地址复制进地址栏(你也可以自己按目录查找),双击ProfileImage...

qq_33835957的博客 7万+

数组越界会发生什么

文章目录一、数组越界会发生什么二、 数组越界详解 一、数组越界会发生什么 C语言非常重视运行时的效率,所以没有进行数组越界检查,而C++继承了C的效率要求,自然也不做数组越界检查。(检查数据越界,编译器就必须在生成的目标代码中加入额外的代码用于程序运行时检测下标是否越界,这就会导致程序的运行速度下降)。看下面一段代码: #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> using namespace std; int main() {

森明帮大于黑虎帮的博客 1万+

实战|2026美团&大众点评餐饮数据抓取:Playwright/Selenium反爬全攻略

核心结论:2026年美团&大众点评的反爬核心是“多维度风控”,需组合使用“住宅IP+设备指纹伪装+真人行为模拟+动态验证处理”,Playwright是最优工具,Selenium仅作为补充。效率优化:单机爬取速度建议控制在“每小时500-800条”,避免高频请求触发风控;分布式爬取需确保每个节点使用独立住宅IP,且行为轨迹不一致。扩展方向集成WASM解密工具,破解2026年美团的Token加密;用AI识别动态点选验证,提升验证通过率;对接大数据平台,对抓取的餐饮数据进行可视化分析。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 2465

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

1.数组越界,是指访问了超出数组定义的内容。实例:inta[2];数组a定义了2个元素!a[0],a[1]:没有越界。a[2]:越界了!对不对?2.计算机全部的内存,其地址是从小到大排列。还是,已经定义的变量(普通变量,指针变量)的内存从小到大排列呢?3.越界的原理的什么?说说原因?a[2]是越界了,而且编译器不会警告的,这是C语言的特性,a[2]可以解析成*(a+2),a是数组的基地址,...

weixin_39616287的博客 3210

Windows Docker Desktop部署MaxKB详细教程

MaxKB(Max Knowledge Base)是一款基于大语言模型(LLM)和检索增强生成(RAG)技术的开源知识库问答系统,旨在帮助企业、教育机构及研究组织高效管理知识并提供智能问答服务。

猿小白的博客 1372

打通ZYNQ的任督二脉:AXI_FIFO数据交互全解析

FIFO(First In First Out,先进先出)是一种经典的数据缓冲结构,就像排队买票一样,先来的人先得到服务。时钟域交叉(CDC):连接不同时钟频率的模块数据缓冲:平衡生产者和消费者的速度差异流量控制:防止数据丢失或溢出input clk,// 输入AXI4-Stream接口(从PS到PL)// 输出AXI4-Stream接口(从PL到PS)// 状态指示信号// 定义状态机状态// 数据缓存// 8个深度的缓存// 流水线处理寄存器。

QQ_778132974的博客 306

Day 0:C语言中的数组越界访问

C语言数组越界是常见的编程陷阱,其本质是连续内存块的直接访问,编译器不进行下标检查。由于C追求高效而牺牲安全性,越界访问属于未定义行为,可能导致内存破坏、程序崩溃或安全漏洞。规避方法包括:严格检查下标合法性、封装数组操作、使用sizeof计算长度、优先选用安全库函数。图示展示了越界访问未定义内存区域的情形。建议开发者养成边界检查习惯,使用工具检测越界问题,并牢记"任何数组访问都要明确边界"的原则。通过封装和自动化检查,可显著提升代码健壮性。

blog.boringhex.top 726

YOLOv11改进,YOLOv11结合DynamicConv(动态卷积),CVPR2024,二次创新C3k2结构

DynamicConv(动态卷积)是一个用于提高卷积神经网络(CNN)性能的技术,核心思想是动态地生成卷积核(filter),而不是使用固定的卷积核。通过引入更多的计算灵活性和适应性来增强卷积操作的表达能力,进而提升模型的性能。专家选择:DynamicConv 通过引入多个“专家”(experts),每个专家学习特定的卷积模式。输入图像的不同部分会选择不同的专家进行卷积。动态卷积核生成:根据输入的不同特征,专家网络动态地生成卷积核,而不是使用固定的卷积核。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 2265

c语言中数组越界怎么办_如果我们使用C语言数组中的越界索引怎么办?

c语言中数组越界怎么办Let’s understand first, what is index out of bounds? 首先让我们了解一下 , 什么是索引超出范围? Let suppose you have an array with 5 elements then the array indexing will be from 0 to 4 i.e. we can access el...

cumtb2002的博客 2907

《UDS协议从入门到精通》系列——图解0x19:读取故障码信息

认识最核心的诊断服务“0x19”!!全网最强图解!一文搞懂所有常用子服务!

车载系统攻城狮 1万+

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

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

因为C语言不检查数组越界,而数组又是我们经常用的数据结构之一,所以程序中经常会遇到数组越界的情况,并且后果轻者读写数据不对,重者程序crash。下面我们来分析一下数组越界的情况:1) 堆中的数组越界因为堆是我们自己分配的,如果越界,那么会把堆中其他空间的数据给写掉,或读取了其他空间的数据,这样就会导致其他变量的数据变得不对,如果是一个指针的话,那么有可能会引起crash2) 栈中的数组越界因为栈是...

weixin_33316051的博客 1562

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

php 数组 没有越界,C++_浅析C语言编程中的数组越界问题,因为C语言不检查数组越界,而 - phpStudy...

浅析C语言编程中的数组越界问题因为C语言不检查数组越界,而数组又是我们经常用的数据结构之一,所以程序中经常会遇到数组越界的情况,并且后果轻者读写数据不对,重者程序crash。下面我们来分析一下数组越界的情况:1) 堆中的数组越界因为堆是我们自己分配的,如果越界,那么会把堆中其他空间的数据给写掉,或读取了其他空间的数据,这样就会导致其他变量的数据变得不对,如果是一个指针的话,那么有可能会引起cras...

weixin_39581099的博客 94

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

论C语言中的数组下标越界

在C语言中一般是不会检查数组的下标范围的,例如: #include int main() { int i; int a[3]; a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4; for (i = 0; i <= 3; i++) { printf("%d\n", a[i]); } return 1; } 上面的代码实际上对a[3]

【昆山人在上海】 5119

c语言数组越界垃圾值,浅析C语言编程中的数组越界问题

2015因为C语言不检查数组越界,而数组又是我们经常用的数据结构之一,所以程序中经常会遇到数组越界的情况,并且后果轻者读写数据不对,重者程序crash。下面我们来分析一下数组越界的情况:1) 堆中的数组越界因为堆是我们自己分配的,如果越界,那么会把堆中其他空间的数据给写掉,或读取了其他空间的数据,这样就会导致其他变量的数据变得不对,如果是一个指针的话,那么有可能会引起crash2) 栈中的数组越界...

weixin_31858863的博客 291

C语言中的溢出(数组越界)

在C陷阱与缺陷中有一样例如下:#include &lt;stdio.h&gt; int main() { int i, a[10]; for(i = 1; i &lt;= 10; ++i) a[i] = 0; return 0; }由于数组a只有10个元素,它们分在在a[0], a[1], ... , a[9], 该程序非法使用了a[10], 结果导致的是该...

HHHHHHep的博客 1万+

C 语言:数组中的越界索引

假设你有一个包含四个元素的数组。然后,数组索引将从 0 到 3,即我们可以访问索引 0 到 3 的元素。但是,如果我们使用大于 3 的索引,它将被调用为越界索引。如果我们使用越界的数组索引,那么编译器将编译甚至运行。但是,不能保证正确的结果。结果可能不确定,它会开始引起许多问题。因此,建议在使用数组索引时要小心。

新华编程特战队 321

【C语言中的陷阱与缺陷】数组访问越界造成的死循环

数组越界访问造成的死循环

surtr1的博客 367
上一篇: C语言的内存管理
下一篇: 关于C语言中函数调用和参数传递机制的探讨
wind19
博客等级 码龄23年 477粉丝 170原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值