数组越界访问会发生什么错误?怎样避免该错误?_SEGMENTATION FAULT IN LINUX 原因与避免...

2023-11-01

原作者( ZX_WING(xing5820@163.com)写得很好,加上之前的确遇到过很多信号问题,产生了很多疑问。

1.什么是“Segmentation fault in Linux”?

我们引用wiki上的一段话来回答这个问题。

A segmentation fault (often shortened to SIGSEGV) is a particular error condition that can occur during the operation of computer software. A segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (for example, attempting to write to a read-only location, or to overwrite part of the operating system).

Segmentation is one approach to memory management and protection in the operating system. It has been superseded by paging for most purposes, but much of the terminology of segmentation is still used, "segmentation fault" being an example. Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy.

On Unix-like operating systems, a process that accesses an invalid memory address receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception.

上述文字没有给出SIGSEGV的定义,仅仅说它是“计算机软件操作过程中的一种错误情况”。文字描述了SIGSEGV在何时发生,即“当程序试图访问不被允许访问的内存区域(比如,尝试写一块属于操作系统的内存),或以错误的类型访问内存区域(比如,尝试写一块只读内存)。这个描述是准确的。为了加深理解,我们再更加详细的概括一下SIGSEGV。

Ø SIGSEGV是在访问内存时发生的错误,它属于内存管理的范畴

Ø SIGSEGV是一个用户态的概念,是操作系统在用户态程序错误访问内存时所做出的处理。

Ø 当用户态程序访问(访问表示读、写或执行)不允许访问的内存时,产生SIGSEGV。

Ø 当用户态程序以错误的方式访问允许访问的内存时,产生SIGSEGV。

从用户态程序开发的角度,我们并不需要理解操作系统复杂的内存管理机制,这是和硬件平台相关的。但是,了解内核发送SIGSEGV信号的流程,对我们理解SIGSEGV是很有帮助的。在《Understanding Linux Kernel Edition 3》和《Understanding the Linux Virtual Memory Manager》相关章节都有一幅总图对此描述,对比之下,笔者认为ULK的图更为直观。

图1. SIGSEGV Overview

图1红色部分展示了内核发送SIGSEGV信号给用户态程序的总体流程。当用户态程序访问一个会引发SIGSEGV的地址时,硬件首先产生一个page fault,即“缺页异常”。在内核的page fault处理函数中,首先判断该地址是否属于用户态程序的地址空间[*]。以Intel的32bit IA32架构的CPU为例,用户态程序的地址空间为[0,3G],内核地址空间为[3G,4G]。如果该地址属于用户态地址空间,检查访问的类型是否和该内存区域的类型是否匹配,不匹配,则发送SIGSEGV信号;如果该地址不属于用户态地址空间,检查访问该地址的操作是否发生在用户态,如果是,发送SIGSEGV信号。

[*]这里的用户态程序地址空间,特指程序可以访问的地址空间范围。如果广义的说,一个进程的地址空间应该包括内核空间部分,只是它不能访问而已。

图2更为详细的描绘了内核发送SIGSEGV信号的流程。在这里我们不再累述图中流程,在后面章节的例子中,笔者会结合实际,描述具体的流程。

图2 SIGSEGV detailed flow

2.指针越界和SIGSEGV

经常看到有帖子把两者混淆,而这两者的关系也确实微妙。在此,我们把指针运算(加减)引起的越界、野指针、空指针都归为指针越界。SIGSEGV在很多时候是由于指针越界引起的,但并不是所有的指针越界都会引发SIGSEGV。一个越界的指针,如果不解引用它,是不会引起SIGSEGV的。而即使解引用了一个越界的指针,也不一定会引起SIGSEGV。这听上去让人发疯,而实际情况确实如此。SIGSEGV涉及到操作系统、C库、编译器、链接器各方面的内容,我们以一些具体的例子来说明。

2.1错误的访问类型引起的SIGSEGV

1 #include  2 #include  3  4 int main() { 5 char* s = "hello world"; 6 7 s[1] = 'H';8 }

这是最常见的一个例子。想当年俺对C语言懵懂的时候,也在校内的BBS上发帖问过,当时还以为这是指针和数组的区别。此例中,”hello world”作为一个常量字符串,在编译后会被放在.rodata节(GCC),最后链接生成目标程序时.rodata节会被合并到text segment与代码段放在一起,故其所处内存区域是只读的。这就是错误的访问类型引起的SIGSEGV。

其在图2中的顺序为:

1 -> 3 -> 4 -> 6 -> 8 -> 11 ->10

2.2访问了不属于进程地址空间的内存

 1 #include  2 #include  3  4 int main() { 5 int* p = (int*)0xC0000fff; 6 7 *p = 10; 8 }

在这个例子中,我们访问了一个属于内核的地址(IA32,32bit)。当然,很少会有人这样写程序,但你的程序可能在不经意的情况下做出这样的行为(这个不经意的行为在后面讨论)。此例在图2的流程:

1 -> 2 -> 11 -> 10

2.3访问了不存在的内存

最常见的情况不外乎解引用空指针了,如:

 1 #include  2 #include  3  4 int main () { 5 int *a = NULL; 6 7 *a = 1; 8 }

在实际情况中,此例中的空指针可能指向用户态地址空间,但其所指向的页面实际不存在。其产生SIGSEGV在图2中的流程为:

1 -> 3 -> 4 -> 5 -> 11 ->10

2.4栈溢出了,有时SIGSEGV,有时却啥都没发生

这也是CU常见的一个月经贴。大部分C语言教材都会告诉你,当从一个函数返回后,该函数栈上的内容会被自动“释放”。“释放”给大多数初学者的印象是free(),似乎这块内存不存在了,于是当他访问这块应该不存在的内存时,发现一切都好,便陷入了深深的疑惑。

 1 #include  2 #include  3 4 int* foo() { 5 int a = 10; 6 7 return &a; 8 } 9 10 int main() { 11 int* b; 12 13 b = foo(); 14 printf ("%d
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数组越界访问会发生什么错误?怎样避免该错误?_SEGMENTATION FAULT IN LINUX 原因与避免... 的相关文章

  • 【期末大作业】语料库--分类、聚类、关系提取

    一 课程要求以及说明 1 使用分类 聚类 关系提取对数据集进行相关的分析 在使用数据集之前 需要用到数据预处理 2 可以在以下方法中选择一种聚类和一种分类技术 聚类 无监督学习 C1 network analysis 网络分析 C2 k m
  • lnmp环境搭建的详细过程(ubuntu22)

    软件及软件版本的信息如下 nginx 1 18 0 mysql 8 0 32 php 8 1 备注 我的ubuntu环境是Windows下基于WSL2的Ubuntu 想看怎么实现的可以看这个文章 https blog csdn net qq
  • CVE-2021-4034 Polkit

    CVE 2021 4034 Polkit 0x01 漏洞介绍 Polkit是一个应用程序级别的工具集 通过定义和审核权限规则 实现不同优先级进程间的通讯 控制决策集中在统一的框架之中 决定低优先级进程是否有权访问高优先级进程 另外Polki
  • 熔断,降级,限流的区别

    熔断 降级 限流 熔断 Circuit Breaking 限流 Rate Limiting 降级 Fallback 熔断 Circuit Breaking 一种用于处理依赖服务故障的策略 当依赖服务出现故障或超时 熔断机制会迅速中断对该服务
  • 【测试设计】使用jenkins 插件Allure生成自动化测试报告

    前言 以前做自动化测试的时候一直用的HTMLTestRunner来生成测试报告 后来也尝试过用Python的PyH模块自己构建测试报告 在后来看到了RobotFramework的测试报告 感觉之前用的测试报告都太简陋 它才是测试报告应该有的
  • 基于SSM + MySql + LayUI的图书管理系统

    点击下载 图书管理系统 文件大小 72M 操作系统 Windows10旗舰版 数据库 MySQL5 7 BookManageSystemLayui src main resources sql 开发工具 idea2021 JDK8 Mave
  • web前端进阶大厂面试资料合集

    最近整理了下web前端面试的资料 包含了web前端 数据结构和算法 计算机基础 版本控制工具 经验分享 视频课程和面试书籍等资料 还有比这更全的没有 废话不多说 直接上干货 欢迎收藏 不用客气 前端 面试官求你别再问我hook了 程序员必须
  • Wing IDE安装与破解方法

    WingIDE的licese破解方法 1 安装WingIDE成功后启动 激活时输入license id CN123 12345 12345 12345 2 点击Continue后弹框 拷贝框中的request code 将其放入脚本中的Re
  • 获取微信小程序登录code和获取手机号code

    index ts 获取应用实例 const app getApp
  • QT自定义槽方法

    本文简介点击窗体上的按钮后 改变窗体标题的方法 在窗体上放置好按钮之后 有以下三步操作 声明 gt 实现 gt 连接 1 声明 在头文件mainwindow h中声明一个槽 private slots void changeTitleSlo
  • pychar常用快捷键及转义符号

    Alt 1 影藏和显示项目列表 Ctrl shift F10 运行代码 Ctrl shift F4 关闭Tab 终端运行面板 Ctrl 注释代码 取消注释 Ctrl d 复制行 Ctrl L 格式化代码 PEP8编码格式 shift Alt
  • CGridCtrl(集成了打印预览与合并单元格)

    ucogrid src zip
  • 算法图解part5:散列表

    算法图解part5 散列表 1 散列 hashing 函数 2 散列表的应用 2 1将散列表用于查找 2 2防止重复 2 3用于缓存 3 冲突 4 性能 4 1填装因子 4 2良好的散列函数 5 总结 6 参考资料 1 散列 hashing
  • python图像处理opencv_Python+OpenCV图像处理——图像二值化的实现

    简介 图像二值化就是将图像上的像素点的灰度值设置为0或255 也就是将整个图像呈现出明显的黑白效果的过程 普通图像二值化 代码如下 import cv2 as cv import numpy as np 全局阈值 def threshold
  • 【深度学习系列】——神经网络的可视化解释

    这是深度学习系列的第三篇文章 欢迎关注原创公众号 计算机视觉联盟 第一时间阅读我的原创 回复 西瓜书手推笔记 还可获取我的机器学习纯手推笔记 深度学习系列 深度学习系列 深度学习简介 深度学习系列 梯度下降算法的可视化解释 动量 AdaGr
  • java面经——基础篇(1)

    目录 1 抽象类和接口有什么区别 2 静态变量和实例变量的区别 3 Integer 和 int 的区别 4 装箱和拆箱的区别 5 JDK JRE JVM 三者之间的关系 6 重载和重写的区别 7 Java 中是否可以重写一个 private
  • Java循环结构的嵌套-day11

    循环结构的嵌套 循环结构的嵌套是指一个循环体内又包含另一个循环结构 嵌套在内部的循环体中还可以嵌套循环结构 这就构成了多重循环 但嵌套的层数建议不要过多 嵌套层数过多会使程序变得难以读懂 常用的3种循环嵌套结构 带条件的循环结构 概念 在多
  • JavaScript的异步编程async、await

    1 async关键字 先说一下async的用法 它作为一个关键字放到函数前面 用于表示函数是一个异步函数 因为async就是异步的意思 异步函数也就意味着该函数的执行不会阻塞后面代码的执行 例如 async function timeout

随机推荐

  • Unity-3D物体的遮罩

    转自 http blog csdn net obilang article details 43878607 大致需要用到的东西 shader 材质 深度摄像机 unity实现2D遮罩找了许多的解决方法 这个是我采取的一种方法 比较便捷 但
  • c++多重继承和虚继承

    多重继承 多重继承是指从多个直接基类中产生派生类的能力 多重继承的派生类继承了所有父类的属性 struct Base1 Base1 default Base1 const string Base1 shared ptr
  • Jenkins+docker自动化部署

    参考文献 Jenkins与Docker的自动化CI CD实战 附源码 李振良 阿良 51CTO博客 遇到的问题 1 我们使用的jdk放置了微信专用的jar 所以自己建了一个基础镜像 参考文献 Docker JDK镜像制作 陌生谁家年少 CS
  • socket编程的 sendto 函数

    http see xidian edu cn cpp html 372 html 相关函数 send sendmsg recv recvfrom socket 头文件 include
  • ceph-pg状态详解

    Creating 含义 PG正在创建 引起原因 创建pool的时候 根据指定的pg数量进行创建pg时出现的状态 正常状态 后果 无 解决方案 无需解决 正常状态之一Peering 含义 PG之间进行互联 就其中的对象和元数据状态达成一致 引
  • 认识区块链,认知区块链— —通证、公链

    引子 上周末分享会 胡子俱乐部请到了两位已经有区块链落地实践的大咖 一个是专注于联盟链的金股链 另外一个就是专注于内容分发领域的ulord 会议议题主要集中在公链的发展以及落地的实践 一上午的讨论 意犹未尽 期间就比较关注的内容 做了笔记
  • CH6-集合 (5个案例实现)

    案例6 1 库存管理系统 案例介绍 1 任务描述 像商城和超市这样的地方 都需要有自己的库房 并且库房商品的库存变化有专人记录 这样才能保证商城和超市正常运转 本例要求编写一个程序 模拟库存管理系统 该系统主要包括系统首页 商品入库 商品显
  • 【随笔记】全志平台 gpio-leds 驱动应用

    硬件信息 内核版本 Linux 4 9 硬件原理 GPIO 通过一颗 MOS 管 2N7002ET1G 接到 LED 负极 LED 正极接电源 GPIO 通过拉高导通 MOS 将 LED 接地 实现点亮 LED 内核配置 配置内核驱动 ma
  • Cannot find name ‘console‘. Do you need to change your target library?ging the ‘lib‘ compiler option

    错误展示 Cannot find name console Do you need to change your target library ging the lib compiler option to include dom 2 co
  • 服务器在机柜中的安装位置,服务器上机柜的安装方法

    服务器上机柜的安装方法 内容精选 换一换 安装依赖时 使用pip3 7 5 install xxx命令安装相关软件时提示无法连接网络 且提示 Could not find a version that satisfies the requi
  • 编译脚本(build.sh),执行脚本(start.sh),停止脚本(stop.sh)

    编写一个服务程序后 通过这三个脚本去编译 执行 停止 build sh脚本文件 bin bash 1 该行是如果出现错误 就退出脚本执行 set e 设置基本环境变量start export LC ALL en US UTF 8 1 BAS
  • Dockerfile、docker-compose、docker网络以及Portainer安装

    文章目录 1 安装mysql主从复制 2 安装redis集群 分布式存储案例 2 1 cluster 集群 模式 docker版 哈希取余分区 一致性哈希算法分区 哈希槽分区 2 2 3主3从redis集群配置 2 3 主从容错切换迁移 数
  • DeepBrainNet论文阅读笔记

    论文题目 MRI signatures of brain age and disease over the lifespan based on a deep brain network and 14 468 individuals worl
  • Caused by: java.lang.ClassNotFoundException: Didn’t find class on path apk Android Studio解决方案

    标签 android studio ClassNotFoundException library 尊重远程 转载请注明出处 http blog csdn net a740169405 article details 50351039 错误原
  • DC-DC自举电容(BOOT)几个问题

    在BUCK电路中 经常会看到一个电容连接在芯片的SW和boot管脚之间 这个电容称之为自举电容 关于这个电容 有以下几个问题 自举电容有什么用 以MPS的buck芯片MP1484为例 规格书中芯片的BS管脚说明如下 在BS和SW之间接一个0
  • 数字信号处理知识点

    数字信号处理知识点 1 频谱图中 横坐标取值范围的含义 2 MATLAB常用函数 2 1 波形产生 2 2 滤波器分析 2 3 滤波器实现 2 4 线性系统变换 2 5 滤波器设计 2 5 1 FIR滤波器 2 5 2 IIR滤波器 2 6
  • vue Cannot create property ‘xxx字段‘ on string

    看一下入参格式是否正确
  • const char *、char const*、char *const三者的区别

    一 const char 对于const char s来说 const char 是指向常量的指针 而不是指针本身为常量 可以不被初始化 该指针可以指向常量也可以指向变量 只是从该指针的角度而言 它所指向的是常量 s是不变的 s是可以改变的
  • git如何提交功能分支代码

    1 当你要写一个功能之前 先创建一个分支 在项目的终端输入 例如 git checkout b login 现在我们就创建了一个login登录分支 输入git branch 可以看到我们正处在login这个分支上面 2 当你写完这个登录功能
  • 数组越界访问会发生什么错误?怎样避免该错误?_SEGMENTATION FAULT IN LINUX 原因与避免...

    原作者 ZX WING xing5820 163 com 写得很好 加上之前的确遇到过很多信号问题 产生了很多疑问 1 什么是 Segmentation fault in Linux 我们引用wiki上的一段话来回答这个问题 A segme