[c语言日寄]越界访问:意外的死循环

【作者主页】siy2333
【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是进阶开发者,这里都能满足你的需求!
【食用方法】1.根据题目自行尝试 2.查看基础思路完善题解 3.学习拓展算法
【Gitee链接】资源保存在我的Gitee仓库:https://gitee.com/siy2333/study
文章目录
- 前言
- 一、案例
- 二、越界访问
- 什么是越界访问
- 越界访问一般发生在什么地方
- 数组操作
- 指针操作
- 字符串操作
- 动态内存分配
- 结构体和联合体操作
- 函数调用和参数传递
- 系统调用和库函数
- 并发和多线程
- 网络编程
- 三、如何避免越界访问
- 数组操作
- 指针操作
- 字符串操作
- 动态内存分配
- 结构体和联合体操作
- 四、回归案例分析
- 总结
前言
越界访问是一种常见的程序错误,本篇文章将基于一个案例,从什么是数组越界,数组越界经常发生在什么地方,如何预防数据越界三方面来详细介绍该错误。
一、案例
查看以下c语言代码,试写出其运行结果,并说明理由:
#include <stdio.h>
int main()
{int i = 0;int arr[] = { 1,2,3,4,5,6,7,8,9,10 };for (i = 0; i <= 12; i++){arr[i] = 0;//数组越界访问printf("%d\t",i);}return 0;
}
这个代码非常简洁,我们可以很容易的发现其中i的范围是1-12,但是arr数组的大小只有10个int类型,出现了越界访问。
我们在vs2022中,在debug、x86环境下,运行该代码,结果如下:

没错,出现了死循环。但是,为什么呢?
二、越界访问
什么是越界访问
越界访问(Out-of-Bounds Access),也称为缓冲区溢出或越界读写,是一种常见的程序错误。它指的是程序试图访问超出其分配的内存空间的数据。这种行为可能会导致程序崩溃或者被利用来进行恶意攻击。
越界访问一般发生在什么地方
数组操作
- 数组索引超出范围:这是最常见的越界访问类型。例如,对于一个大小为10的数组,尝试访问第11个元素(索引为10)就会导致越界。
- 循环控制不当:在循环中,如果循环条件或索引更新逻辑有误,可能会导致索引超出数组范围。例如:
int arr[10];
for (int i = 0; i <= 10; i++) { // 错误:i <= 10arr[i] = i;
}
指针操作
- 未初始化的指针:如果指针没有被正确初始化,它可能指向一个随机的内存地址,解引用这样的指针会导致越界访问。
- 野指针:指针指向了一个已经被释放或从未分配的内存区域。
- 指针偏移错误:通过指针进行偏移操作时,如果偏移量计算错误,可能会导致指针指向无效的内存地址。
int arr[10];
int* ptr = arr;
ptr += 11; // 错误:ptr指向了数组范围之外
*ptr = 42; // 越界访问
字符串操作
- 字符串长度错误:在处理字符串时,如果字符串长度计算错误,可能会导致越界访问。例如,使用strcpy时,目标字符串的缓冲区大小不足以容纳源字符串,就会导致越界。
- 字符串函数使用不当:使用如strcpy、strcat等不安全的字符串函数,而不是strncpy、strncat等安全的函数,容易导致越界。例如:
char dest[10];
char src[] = "Hello, World!";
strcpy(dest, src); // 错误:src长度超过dest的大小
动态内存分配
- 分配大小错误:在使用malloc、calloc或realloc分配内存时,如果分配的大小不足以满足需求,可能会导致越界访问。
- 释放后使用:释放了动态分配的内存后,仍然尝试访问该内存区域,会导致越界访问。例如:
int* ptr = (int*)malloc(10 * sizeof(int));
free(ptr);
*ptr = 42; // 错误:ptr指向的内存已经释放
结构体和联合体操作
- 结构体成员访问错误:如果结构体的成员访问逻辑有误,可能会导致越界访问。例如,访问结构体中不存在的成员。
- 联合体使用不当:联合体中的成员共享同一块内存,如果访问联合体成员时没有正确处理,可能会导致越界访问。
函数调用和参数传递
- 函数参数错误:传递给函数的参数如果超出预期范围,可能会导致函数内部的越界访问。例如,传递给函数的数组指针和数组大小参数不匹配。
- 递归调用错误:在递归函数中,如果递归条件或递归深度控制不当,可能会导致越界访问。
系统调用和库函数
- 系统调用参数错误:在调用系统函数时,如果传递的参数不正确,可能会导致越界访问。例如,使用read或write系统调用时,传递的缓冲区大小参数错误。
- 库函数使用不当:使用标准库函数时,如果参数不正确或使用方式不当,可能会导致越界访问。例如,使用memcpy时,目标缓冲区大小不足以容纳源数据。
并发和多线程
- 线程同步错误:在多线程环境中,如果线程同步机制不正确,可能会导致多个线程同时访问同一块内存,从而导致越界访问。
- 线程局部存储错误:如果线程局部存储的使用不当,可能会导致越界访问。
网络编程
- 网络数据处理错误:在处理网络数据时,如果数据长度计算错误或缓冲区管理不当,可能会导致越界访问。例如,接收的网络数据长度超过缓冲区大小。
- 协议解析错误:在解析网络协议时,如果协议解析逻辑有误,可能会导致越界访问。
三、如何避免越界访问
数组操作
- 检查索引范围:在访问数组元素之前,始终检查索引是否在合法范围内。
int arr[10];
for (int i = 0; i < 10; i++) {arr[i] = i;
}
- 使用安全的数组操作函数:在C语言中,可以使用如strncpy、strncat等安全的字符串操作函数,而不是strcpy、strcat等可能导致越界的函数。
char dest[10];
char src[] = "Hello, World!";
strncpy(dest, src, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0'; // 确保字符串以null字符结尾
指针操作
- 初始化指针:确保指针在使用前被正确初始化。
int* ptr = NULL;
ptr = (int*)malloc(10 * sizeof(int));
if (ptr == NULL) {// 处理内存分配失败的情况
}
- 检查指针有效性:在解引用指针之前,检查指针是否指向有效的内存地址。
if (ptr != NULL) {*ptr = 42;
}
- 避免野指针:释放指针后,立即将其设置为NULL,以避免后续误用。
free(ptr);
ptr = NULL;
字符串操作
使用安全的字符串函数:使用如strncpy、strncat等安全的字符串操作函数,而不是strcpy、strcat等可能导致越界的函数。
char dest[10];
char src[] = "Hello, World!";
strncpy(dest, src, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0'; // 确保字符串以null字符结尾
动态内存分配
- 检查分配大小:在使用malloc、calloc或realloc分配内存时,确保分配的大小足以满足需求。
int* ptr = (int*)malloc(10 * sizeof(int));
if (ptr == NULL) {// 处理内存分配失败的情况
}
- 释放后不再使用:释放了动态分配的内存后,立即将指针设置为NULL,以避免后续误用。
free(ptr);
ptr = NULL;
结构体和联合体操作
- 检查结构体成员访问:在访问结构体成员时,确保成员存在且访问逻辑正确。
struct {int a;int b;
} s;
s.a = 10; // 正确
// s.c = 20; // 错误:结构体中没有成员c
- 正确使用联合体:联合体中的成员共享同一块内存,确保访问联合体成员时逻辑正确。
union {int a;char b[4];
} u;
u.a = 0x12345678;
// 正确访问联合体成员
四、回归案例分析
我们在第八行添加一个断点,并对代码进行调试:

我们在监视窗口下,逐步观察值的变化:

可以看到,我们的前十次for循环是正常运行的:
那么问题就出现在数组越界后了,我们可以修改监视窗口,使得arr[10]、arr[11]、arr[12]也可以显示出来。

此时,我们可以发现,arr[10]、arr[11]是随机值,但是arr[12]储存了一个值。当我们执行到arr[12]被修改时,监视如下:

没错!i的值被改变了!那么我们可以猜测,i的值是否就是储存在arr[12]处?使用监视验证这个猜想:

答案出来了,可以看见arr[12]的地址和i的地址一模一样,即因为数组越界访问,使得i的值永远无法达到跳出循环的条件。
因此,出现了死循环现象。
总结
通过本文的案例分析,我们深入探讨了数组越界访问这一常见错误。越界访问不仅会导致程序崩溃,还可能引发安全漏洞。本文从越界访问的定义、常见场景及预防方法三个方面进行了详细阐述。在案例中,通过调试,我们发现数组越界访问导致循环变量 i 的值被意外修改,从而引发死循环。
关注窝,每三天至少更新一篇优质c语言题目详解~
[专栏链接QwQ] :⌈c语言日寄⌋CSDN
[关注博主ava]:siy2333
感谢观看~ 我们下次再见!!
相关文章:
[c语言日寄]越界访问:意外的死循环
【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…...
「蓝桥杯题解」蜗牛(Java)
题目链接 这道题我感觉状态定义不太好想,需要一定的经验 import java.util.*; /*** 蜗牛* 状态定义:* dp[i][0]:到达(x[i],0)最小时间* dp[i][1]:到达 xi 上方的传送门最小时间*/public class Main {static Scanner in new Scanner(System.in);static f…...
新时代架构SpringBoot+Vue的理解(含axios/ajax)
文章目录 引言SpringBootThymeleafVueSpringBootSpringBootVue(前端)axios/ajaxVue作用响应式动态绑定单页面应用SPA前端路由 前端路由URL和后端API URL的区别前端路由的数据从哪里来的 Vue和只用三件套axios区别 引言 我是一个喜欢知其然又知其所以然的…...
视频外绘技术总结:Be-Your-Outpainter、Follow-Your-Canvas、M3DDM
Diffusion Models专栏文章汇总:入门与实战 前言:视频Inpaint的技术很火,但是OutPaint却热度不高,这篇博客总结比较经典的几篇视频Outpaint技术。其实Outpaint在runway等工具上很火,可是学术界对此关注比较少,博主从这三年的顶会中找到了最具代表性的三篇论文解读。 目录 …...
HashMap讲解
在Java开发中,HashMap 是最常用的数据结构之一,它不仅提供了键值对的快速存储和检索功能,还具备较高的性能和较低的空间占用。但很多开发者对其底层原理并不清楚,今天我们将详细解析HashMap的内部结构,并用通俗的方式解…...
AIP-133 标准方法:Create
编号133原文链接AIP-133: Standard methods: Create状态批准创建日期2019-01-23更新日期2019-01-23 在REST API中,通常向集合URI(如 /v1/publishers/{publisher}/books )发出POST请求,在集合中创建新资源。 面向资源设计&#x…...
aerodrome交易所读合约分析
池地址 0xb2cc224c1c9fee385f8ad6a55b4d94e92359dc59token0 0x4200000000000000000000000000000000000006token1 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913tickSpacing 100stakedLiquidity 4579376109215388530 snapshotCumulativesInside tickLower tickUpperslot0 …...
ts 基础核心
吴悠讲编程 : 20分钟学会TypeScript 无废话速成TS https://www.bilibili.com/video/BV1gX4y177Kf...
[内网安全] 内网渗透 - 学习手册
这是一篇专栏的目录文档,方便读者系统性的学习,笔者后续会持续更新文档内容。 如果没有特殊情况的话,大概是一天两篇的速度。(实验多或者节假日,可能会放缓) 笔者也是一边学习一边记录笔记,如果…...
FaceFusion
文章目录 一、关于 FaceFusion预览 二、安装三、用法 一、关于 FaceFusion FaceFusion 是行业领先的人脸操作平台 github : https://github.com/facefusion/facefusion官方文档:https://docs.facefusion.io/Discord : https://discord.com/invite/facefusion-1141…...
使用github提交Pull Request的完整流程
文章目录 1.Fork仓库2. git clone 仓库在本地3.对项目进行修改开发4.上传项目到远程仓库操作补充1. git add .2. git commit -m "提交信息"3. git pull4. git push总结完整工作流程示例 5.将更新的项目pull Request给原来的仓库主人 当多人进行项目的开发的时候&…...
游戏与硬件深度协同,打造更精细的体验优化
高画质的游戏往往带来手机的发热和卡顿从而影响游戏体验。开发者希望能够获取到手机运行的实时状态,从而能够进行主动的负载调节,将手机发热时游戏体验影响降到最低;同时手机也可以通过游戏传入的关键场景如"正在下载资源"“团战中…...
简笔画生成smplx sketch2pose
目录 smplx安装: patch diff 命令行运行 pyrender报错: 解决方法: 这篇博客也不错,值得推荐 sketch2pose github地址: GitHub - kbrodt/sketch2pose: Sketch2Pose: Estimating a 3D Character Pose from a Bitmap Sketch smplx安装: 只能用这个版本,别的版本报错…...
SpringCloud系列教程:微服务的未来(十七)监听Nacos配置变更、更新路由、实现动态路由
前言 在微服务架构中,API 网关是各个服务之间的入口点,承担着路由、负载均衡、安全认证等重要功能。为了实现动态的路由配置管理,通常需要通过中心化的配置管理系统来实现灵活的路由更新,而无需重启网关服务。Nacos 作为一个开源…...
复古壁纸中棕色系和米色系哪个更受欢迎?
根据最新的搜索结果,我们可以看到棕色系和米色系在复古壁纸设计中都非常受欢迎。以下是对这两种颜色系受欢迎程度的分析: 棕色系 受欢迎程度:棕色系在复古壁纸中非常受欢迎,因为它能够营造出温暖、质朴和自然的氛围。棕色系的壁纸…...
Linux 非阻塞IO
Linux 非阻塞IO 1. fcntl() 在Linux操作系统中,fcntl() 是一个用于操作文件描述符的系统调用。它提供了多种功能,包括控制文件描述符的属性、管理文件锁定、设置文件的非阻塞模式等。 本文只截取了用于IO模型的 fcntl() 部分内容, fcntl() …...
go入门Windows环境搭建
简介 Go 即 Golang,是 Google 公司 2009 年 11 月正式对外公开的一门编程语言。 根据 Go 语言开发者自述,近 10 多年,从单机时代的 C 语言到现在互联网时代的 Java,都没有令人满意的开发语言,而 C往往给人的感觉是&a…...
es6中关于let的使用以及案例,包括但不限于块级作用域,不允许重复声明,没有变量提升,暂存性死区,不与顶层对象挂钩
ES6 let 关键字完整指南 1. 块级作用域 1.1 let vs var 作用域对比 // var - 函数作用域 function varExample() {var x 1;if (true) {var x 2; // 同一个 xconsole.log(x); // 2}console.log(x); // 2 }// let - 块级作用域 function letExample() {let x 1;if (true…...
IO进程线程复习
文件IO和标准IO的区别 文件IO: 1.系统提供的用于输入输出的函数 2.有文件描述符0,1,2 3.open,close,puts,gets 4.可以操作任意类型的文件,不能操作目录 5.无缓存机制 标准IO: 1.C库提供的用于输入输出的函数 2.有文件流…...
Mybatis初步了解
mysql缓存:根据sql语句进入缓存,如果sql语句多加一个空格就进入不到同一个缓存,另外数据库数据发生了更新,缓存中的数据不会同步。 延迟加载:先查询基本信息,再查询其他信息,而不是一次就查询出…...
基于PyQt设计的智能停车管理系统
文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】设计意义【4】国内外研究现状【6】摘要1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】VSCODE【2】python【3】ptqt【4】HyperLPR31.5 参考文献二、安装Python环境1.1 环境介绍**1.2 Python版本介…...
linux系统中的 scp的使用方法
SCP(Secure Copy Protocol)是一种通过加密的方式在本地主机和远程主机之间安全地传输文件的协议。 它是基于SSH协议的扩展,允许用户在不同主机之间进行文件复制和传输,是Linux和Unix系统中常用的工具之一。 在嵌入式Linux软件的…...
短连接项目01---基本框架的搭建和测试运行
文章目录 1.什么是短链2.仓库的创建3.项目的创建4.配置文件的修改5.三个模块的创建5.1如何创建5.2类型的选择5.3包的完善 6.yml文件的配置7.启动类的测试8可能会出现的问题 1.什么是短链 下面的这个就是一个长的url,我们的短链里面的链就是链接,也就是我…...
Unity阿里云OpenAPI 获取 Token的C#【记录】
获取Token using UnityEngine; using System; using System.Text; using System.Linq; using Newtonsoft.Json.Linq; using System.Security.Cryptography; using UnityEngine.Networking; using System.Collections.Generic; using System.Globalization; using Cysharp.Thr…...
2023年吉林省职业院校技能大赛网络系统管理样题-网络配置(华三代码)
目录 附录1:拓扑图 附录2:地址规划表 1.S1 2.S3 3.S4 4.S5 5.S7 6.S8 7.S9 8.R1 9.R2 10.R3 11.EG1 12.EG2 13.AC1 14.AC2 附录1:拓扑图 编号 型号...
WSL 安装cuDNN
WSL 安装cuDNN 参考文档:https://docs.nvidia.com/deeplearning/cudnn/installation/latest/linux.html#verifying-the-install-on-linux 1. 下载相应包 根据下方下载地址进入下载界面,并选择与自己电脑相对应的平台执行图中的命令 下载地址࿱…...
SSRF漏洞学习总结
一、SSRF漏洞 1.原理 SSRF(Server-Side Request Forgery,服务器端请求伪造)是一种安全漏洞,攻击者利用这个漏洞可以诱使服务器端发起由攻击者构造的请求。这种攻击通常发生在应用接受来自用户的输入,并且该输入用于构…...
stack 和 queue容器的介绍和使用
1.stack的介绍 1.1stack容器的介绍 stack容器的基本特征和功能我们在数据结构篇就已经详细介绍了,还不了解的uu, 可以移步去看这篇博客哟: 数据结构-栈数据结构-队列 简单回顾一下,重要的概念其实就是后进先出,栈在…...
Windows中本地组策略编辑器gpedit.msc打不开/微软远程桌面无法复制粘贴
目录 背景 解决gpedit.msc打不开 解决复制粘贴 剪贴板的问题 启用远程桌面剪贴板与驱动器 重启RDP剪贴板监视程序 以上都不行?可能是操作被Win11系统阻止 最后 背景 远程桌面无法复制粘贴,需要查看下主机策略组设置,结果按WinR输入…...
(2023 RESS ) Federated multi-source domain adversarial adaptation framework
📚 研究背景与挑战 机械设备的故障诊断对于保障生产效率和安全至关重要。传统的智能诊断方法依赖于大量的训练数据,但在实际工业场景中,数据收集受到经济和时间因素的限制。更棘手的是,由于行业竞争和隐私安全问题,不…...
