数组越界如何产生段错误

2024-06-07 16:18
文章标签 数组 错误 产生 越界

本文主要是介绍数组越界如何产生段错误,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

数组越界VS段错误

1 栈中数组越界访问

1.1 示例代码
#include<stdio.h>int main(int argc, char *argv[]){printf("0x%x\n", (unsigned int)(-2));int a[5] = {0};int i;printf("%d\n", getpid());sleep(100);for(i = 0;; i ++){printf("0x%lx->%d\n", a + i, a[i]);}return 0;
}
1.2 测试步骤
(1)编译执行

这里写图片描述

(2)根据PID在proc下面查看进程虚拟地址空间分布

由上图得知,PID=2488,查看/proc/2488/maps文件,内容如下:
这里写图片描述

(3)程序执行结果

这里写图片描述

(4)结论

由/proc/2488/maps文件可以得知:栈stack的范围是:[0x7ffd5c0c1000, 0x7ffd5c0e2000),而由程序执行结果来看,从地址0x7ffd5c0e1ffc处取出一个32位的整数是正常的,但是当从地址0x7ffd5c0e2000处取出一个整数的时候,程序出现段错误。我们可以由文件/proc/2488/maps得到这样的结论:0x7ffd5c0e2000是虚拟地址空间[stack]和[vvar]之间留的空洞,可用于捕获越界访问异常。

2 BSS段中数组越界访问

2.1 示例代码
#include<stdio.h>int a[5] = {0};int main(int argc, char *argv[]){printf("0x%x\n", (unsigned int)(-2));int i;printf("%d\n", getpid());sleep(30);for(i = 0;; i ++){printf("0x%lx->%d\n", (unsigned long)(a + i), a[i]);}return 0;
}
2.2测试步骤
(1)编译执行

这里写图片描述

(2)根据PID在proc下面查看进程虚拟地址空间分布

由上图得知,PID=2645,查看/proc/2645/maps文件,内容如下:
这里写图片描述

(3)执行结果

这里写图片描述

(4)结论

由/proc/2645/maps文件可以得知:BSS段的范围是:[0x 00601000, 0x00602000),而由程序执行结果来看,从地址0x601ffc处取出一个32位的整数是正常的,但是当从地址0x00602000处取出一个整数的时候,程序出现段错误。我们可以由文件/proc/2645/maps得到这样的结论:0x00602000是虚拟地址空间BSS段和堆区之间留的空洞,可用于捕获越界访问异常。

3 堆中数组越界访问

3.1 示例代码
#include<stdio.h>
#include<stdlib.h>int main(int argc, char *argv[]){printf("0x%x\n", (unsigned int)(-2));int *a = (int *)malloc(10 * sizeof(int));int i;printf("%d\n", getpid());sleep(30);for(i = 0;; i ++){printf("0x%lx->%d\n", (unsigned long)(a + i), a[i]);}return 0;
}
3.2测试步骤
(1)编译执行

这里写图片描述

(2)根据PID在proc下面查看进程虚拟地址空间分布

由上图得知,PID=2690,查看/proc/2690/maps文件,内容如下:
这里写图片描述

(3)执行结果

这里写图片描述

(4)结论

由/proc/2690/maps文件可以得知:堆的范围是:[0x012a5000, 0x012c6000),而由程序执行结果来看,从地址0x12c5ffc处取出一个32位的整数是正常的,但是当从地址0x012c6000处取出一个整数的时候,程序出现段错误。我们可以由文件/proc/2690/maps得到这样的结论:0x012c6000是虚拟地址空间堆区和mmap内存区域之间留的空洞,可用于捕获越界访问异常。

4 结论

  linux操作系统无法准确捕获越界访问,只能通过在虚拟地址空间的各个分离的区域之间设置虚拟地址空洞来捕获越界访问导致的异常。

这篇关于数组越界如何产生段错误的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1039675

相关文章

在MySQL执行UPDATE语句时遇到的错误1175的解决方案

《在MySQL执行UPDATE语句时遇到的错误1175的解决方案》MySQL安全更新模式(SafeUpdateMode)限制了UPDATE和DELETE操作,要求使用WHERE子句时必须基于主键或索引... mysql 中遇到的 Error Code: 1175 是由于启用了 安全更新模式(Safe Upd

SpringBoot中的404错误:原因、影响及解决策略

《SpringBoot中的404错误:原因、影响及解决策略》本文详细介绍了SpringBoot中404错误的出现原因、影响以及处理策略,404错误常见于URL路径错误、控制器配置问题、静态资源配置错误... 目录Spring Boot中的404错误:原因、影响及处理策略404错误的出现原因1. URL路径错

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题

《解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题》本文主要讲述了在使用MyBatis和MyBatis-Plus时遇到的绑定异常... 目录myBATis-plus-boot-starpythonter与mybatis-spring-b

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

MCU7.keil中build产生的hex文件解读

1.hex文件大致解读 闲来无事,查看了MCU6.用keil新建项目的hex文件 用FlexHex打开 给我的第一印象是:经过软件的解释之后,发现这些数据排列地十分整齐 :02000F0080FE71:03000000020003F8:0C000300787FE4F6D8FD75810702000F3D:00000001FF 把解释后的数据当作十六进制来观察 1.每一行数据