0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

什么是段错误?

工程师 来源:聚优致成 作者:聚优致成 2020-09-11 14:04 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

来源:聚优致成

一、什么是段错误?一旦一个程序发生了越界访问,cpu 就会产生相应的保护,于是 segmentation fault 就出现了,通过上面的解释,段错误应该就是访问了不可访问的内存。

这个内存区要么是不存在的,要么是受到系统保护的,还有可能是缺少文件或者文件损坏。

二、段错误产生的原因下面是一些典型的段错误的原因:

非关联化空指针——这是特殊情况由内存管理硬件

试图访问一个不存在的内存地址(在进程的地址空间)

试图访问内存的程序没有权利(如内核结构流程上下文)

试图写入只读存储器(如代码段)

1、访问不存在的内存地址

在C代码,分割错误通常发生由于指针的错误使用,特别是在C动态内存分配。非关联化一个空指针总是导致段错误。

但野指针和悬空指针指向的内存,可能会或可能不会存在,而且可能或不可能是可读的还是可写的,因此会导致瞬态错误。

#include 《stdio.h》int main (void){ int *ptr = NULL; *ptr = 0; return 0;}输出结果:段错误(核心已转储)

现在,非关联化这些变量可能导致段错误:非关联化空指针通常会导致段错误,阅读时从野指针可能导致随机数据但没有段错误,和阅读从悬空指针可能导致有效数据,然后随机数据覆盖。

2、访问系统保护的内存地址

#include 《stdio.h》 int main (void){ int *ptr = (int *)0; *ptr = 100; return 0;}输出结果:段错误(核心已转储)

3、访问只读的内存地址

写入只读存储器提出了一个 segmentation fault,这个发生在程序写入自己的一部分代码段或者是只读的数据段,这些都是由操作系统加载到只读存储器。

#include 《stdio.h》#include 《string.h》 int main (void){ char *ptr = “test”; strcpy (ptr, “TEST”); return 0;}输出结果:段错误(核心已转储)

#include 《stdio.h》 int main (void){ char *ptr = “hello”; *ptr = ‘H’; return 0;}输出结果:段错误(核心已转储)

上述例子ANSI C代码通常会导致段错误和内存保护平台。它试图修改一个字符串文字,这是根据ANSI C标准未定义的行为。大多数编译器在编译时不会抓,而是编译这个可执行代码,将崩溃。

包含这个代码被编译程序时,字符串“hello”位于rodata部分程序的可执行文件的只读部分数据段。

当加载时,操作系统与其他字符串和地方常数只读段的内存中的数据。当执行时,一个变量 ptr 设置为指向字符串的位置,并试图编写一个H字符通过变量进入内存,导致段错误。

编译程序的编译器不检查作业的只读的位置在编译时,和运行类unix操作系统产生以下运行时发生 segmentation fault。

可以纠正这个代码使用一个数组而不是一个字符指针,这个栈上分配内存并初始化字符串的值:

#include 《stdio.h》 int main (void){ char ptr[] = “hello”; ptr[0] = ‘H’; return 0;}

即使不能修改字符串(相反,这在C标准未定义行为,在C char *类型,所以没有隐式转换原始代码,在c++的 const char *类型,因此有一个隐式转换,所以编译器通常会抓住这个特定的错误。

4、空指针废弃

因为是一个很常见的程序错误空指针废弃(读或写在一个空指针,用于C的意思是“没有对象指针”作为一个错误指示器),大多数操作系统内存访问空指针的地址,这样它会导致段错误。

#include 《stdio.h》 int main (void){ int *ptr = NULL; printf (“%d\n”, *ptr); return 0;}输出结果:段错误(核心已转储)

这个示例代码创建了一个空指针,然后试图访问它的值(读值)。在运行时在许多操作系统中,这样做会导致段错误。

非关联化一个空指针,然后分配(写一个值到一个不存在的目标)也通常会导致段错误。

#include 《stdio.h》 int main (void){ int *ptr = NULL; *ptr = 1; return 0;}输出结果:段错误(核心已转储)

下面的代码包含一个空指针,但当编译通常不会导致段错误,值是未使用的。因此,废弃通常会被优化掉,死代码消除。

#include 《stdio.h》 int main (void){ int *ptr = NULL; *ptr; return 0;}

还有,比如malloc 动态分配内存,释放、置空完成后,不可再使用该指针。

#include 《stdio.h》#include 《stdlib.h》#include 《string.h》 int main(){ char* str=(char* )malloc(100); if(*str) { return; } strcpy(str,“hello”); printf(“%s\n”,str); free(str); str=NULL; strcpy(str,“abcdef”); return 0;}输出结果:hello段错误 (核心已转储)

5、堆栈溢出

#include 《stdio.h》#include 《string.h》 int main (void){ main (); return 0;}输出结果:段错误(核心已转储)

上述例子的无限递归,导致的堆栈溢出会导致段错误,但无线递归未必导致堆栈溢出,优化执行的编译器和代码的确切结构。在这种情况下,遥不可及的代码(返回语句)行为是未定义的。

因此,编译器可以消除它,使用尾部调用优化,可能导致没有堆栈使用。其他优化可能包括将递归转换成迭代,给出例子的结构功能永远会导致程序运行,虽然可能不是其他堆栈溢出。

6、内存越界(数组越界,变量类型不一致等)

#include 《stdio.h》int main (void){ char test[10]; printf (“%c\n”, test[100000]); return 0;}输出结果:段错误(核心已转储)

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    183

    文章

    7646

    浏览量

    146167
  • 编程
    +关注

    关注

    90

    文章

    3723

    浏览量

    97439
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    NXP产品标记错误信息通知解读

    NXP产品标记错误信息通知解读 在电子行业,产品的质量和准确性至关重要。近日,NXP向购买其产品的客户发出了一份质量信息通知,涉及产品ASC8850AET和ASC8852AET的标记错误问题。下面
    的头像 发表于 04-08 16:30 126次阅读

    CAN总线报错看不懂?5种错误帧+5步排查法一次讲清

    CAN总线通信异常?错误帧频繁出现?本文详解五种错误帧类型,并提供五步排查法,助你快速定位问题根源。错误帧的作用错误帧是CAN总线用于错误
    的头像 发表于 03-16 11:36 425次阅读
    CAN总线报错看不懂?5种<b class='flag-5'>错误</b>帧+5步排查法一次讲清

    机器学习和深度学习中需避免的 7 个常见错误与局限性

    无论你是刚入门还是已经从事人工智能模型相关工作一时间,机器学习和深度学习中都存在一些我们需要时刻关注并铭记的常见错误。如果对这些错误置之不理,日后可能会引发诸多麻烦!只要我们密切关注数据、模型架构
    的头像 发表于 01-07 15:37 350次阅读
    机器学习和深度学习中需避免的 7 个常见<b class='flag-5'>错误</b>与局限性

    瀚海微SD NAND/TF卡数据损坏与校验错误(含CRC错误、数据比对失败)问题解析

    数据损坏与校验错误是瀚海微SD NAND/TF卡在数据存储与传输过程中的关键故障,除常见的CRC错误外,数据比对失败(读取数据与写入数据不一致)是核心表现形式,直接影响数据准确性,在工业控制、高清存储等场景中可能引发严重后果。以下从故障表现、成因及解决方案展开详细说明。
    的头像 发表于 11-30 15:15 1136次阅读

    路由器TACACS+账号登录时经常报用户密码错误的问题分析

    某地M6000-S开启TACACS+账号登录认证后,发现设备登录经常会上报用户密码错误,过一时间才恢复正常。
    的头像 发表于 11-14 09:55 531次阅读
    路由器TACACS+账号登录时经常报用户密码<b class='flag-5'>错误</b>的问题分析

    Cortex-M0+处理器的HardFault错误介绍

    在ARM处理器中,如果一个程序产生了错误并且被处理器检测到,就会产生错误异常。Cortex-M0+处理器只有一种异常用以处理错误:HardFault。
    的头像 发表于 10-14 10:50 3647次阅读
    Cortex-M0+处理器的HardFault<b class='flag-5'>错误</b>介绍

    分析负载特性时,有哪些常见的错误或误区?

    分析负载特性时,很多人会因 “想当然套用经验”“忽略实际场景细节” 或 “混淆概念” 导致判断偏差,进而让报警阈值调整失效(如误报、漏报)。以下是 6 个最常见的错误 / 误区,附错误表现、危害
    的头像 发表于 10-10 17:03 1098次阅读

    如何解决I/O时钟布局器错误

    在 I/O 时钟布局器阶段可能会发生错误,指出该工具无法对该时钟结构进行布局,直至最后 BUFG 仍然无法完成布局。
    的头像 发表于 09-23 16:05 1314次阅读

    知晓常见的铜缆安装错误并避免

    铜缆(如网线、电话线等)是网络和数据传输的基础设施,但在安装过程中,由于操作不当或忽视细节,常出现各种错误,导致网络性能下降甚至故障。以下是常见的铜缆安装错误及预防措施,帮助您避免踩坑: 一、线缆
    的头像 发表于 09-16 10:42 1295次阅读

    国巨贴片电容的电压标识有哪些常见错误

    国巨贴片电容的电压标识在识别和使用过程中可能存在一些常见错误,这些错误可能源于标识本身的模糊性、不同系列产品的差异、对标识规则的误解,或使用环境的影响。以下是具体分析: 一、标识模糊或缺失导致的错误
    的头像 发表于 08-28 16:51 945次阅读

    【EASY EAI Orin Nano开发板试用体验】PP-OCRV5文字识别实例搭建与移植

    鲁班猫RK3588s开发板)上安装完毕: PaddleOCR 3.0提供了一用于测试软件功能的Python实例,只要能运行完毕,哪怕是出现了错误,那也说明了软件安装成功:from
    发表于 08-18 16:57

    避雷!树莓派初学者常犯的5个错误

    如果你刚刚入手树莓派,你就会知道它潜力无穷,几乎能实现你想到的任何功能。然而,这种自由也让你可能在不知不觉中做出对系统有害的操作。在本文中,我将介绍要避免犯哪些错误。初学者最常犯的错误包括:损坏SD
    的头像 发表于 07-22 17:16 1573次阅读
    避雷!树莓派初学者常犯的5个<b class='flag-5'>错误</b>!

    【EASY EAI Orin Nano开发板试用体验】使用Linux posix文件读取接口和LVGL的animimg(图像动画)控件实现动画播放以及

    比较简单,但是一开始被带偏了,实现摄像头显示直接用lv_image控件即可,并不需要lv_canvas(画布)控件,画布的使用方法比较复杂,且容易因操作不当造成错误。添加LVGL定时器方法如下
    发表于 07-22 00:34

    电商API常见错误排查指南:避免集成陷阱

      在电商平台开发中,API集成是连接系统、实现数据交换的核心环节。然而,许多开发者在集成过程中常遇到错误,导致项目延迟、数据丢失或用户体验下降。本文将逐步介绍常见错误类型、排查方法以及预防策略
    的头像 发表于 07-11 14:21 2297次阅读
    电商API常见<b class='flag-5'>错误</b>排查指南:避免集成陷阱

    如何验证CAN控制器的错误响应机制?

    CAN节点的稳定性、可靠性和安全性得益于其强大的错误管理机制。上一篇文章我们介绍了CAN控制器的错误管理机制的工作原理。本文将基于其工作原理及ISO16845-1:2016标准,为大家介绍
    的头像 发表于 04-30 18:24 1025次阅读
    如何验证CAN控制器的<b class='flag-5'>错误</b>响应机制?