危险的指针---字符指针和字符数组指针所导致的段错误

news2024/9/21 4:40:23

前言

(1)今天在编写采用平台总线模型的LED点灯程序时候,发现每次装载驱动,都会报如下错误,最后一行报错说段错误。
(2)我一开始以为是因为自己的平台总线模型写错了,花了很长时间进行对比没有发现问题,最终使用printk定位到了问题所在。

在这里插入图片描述

问题代码部分

(1)我当时采用printk进行打印调试,最终定位问题在这一块。
(2)于是我就开始研究这三行代码。发现一个非常有意思的地方,这个地方的报错,有时候不会出现!他时好时坏,导致我定位问题花了很长时间。
(3)最后发现,我传入的gpios[i].name是一个字符指针,而别人的代码是传入的gpios[i].name是一个字符数组指针。

在这里插入图片描述

(4)最终我将结构体进行了如下更改,之后问题就解决了

/**  原来的结构体  **/
struct gpio_desc{
	int gpio;   //引脚编号
    char *name; //名字
};

/**  更改后的结构体  **/
struct gpio_desc{
	int gpio;   //引脚编号
    char name[128]; //名字
};

字符指针和字符数组指针的区别

传入字符指针,是否符合语法

(1)首先,我们先看看sprintf()的函数声明,我们可以看到,第一个参数是一个char*类型数据。
(2)那么,如果我们传入一个字符指针其实是符合语法规则的。

int sprintf(char *str, const char *format, ...);

为什么会报错

(1)符合语法,但是为啥会报错呢?这个就要讲到字符指针和字符数组指针的区别了。
(2)用最简单通俗的话来讲,字符数组指针其实就是字符指针的升级版本。为啥这么说呢?因为,字符数组指针和字符指针都是一个指针,只不过他们所指向的区域有所不同。
(3)字符数组指针
<1>他首先需要向系统申请一块未被使用的内存区域,比如我这里设置的是char name[128];那么就会向内存申请到一个连续的128字节未被使用的内存。
<2>申请到这一块内存之后,系统将会返回这一段内存的首地址。
(4)字符指针。当你申请了一个字符指针之后,他可能指向任何一块地方,哪一个地方可能是被申请的空间,可能是未被申请的空间。他所指向的区域是未知的,如果你没有主动给他赋值,那么他就是传说中的野指针
(5)注释分割符上下两个代码等价

char name[128];
/***  上下两个代码等价  ***/
char *name;
name = (char*)malloc(128*sizeof(char));

这个问题在所有芯片上都会进行报错吗?

MMU的作用

(1)在抛出这个问题之前,我们需要思考一个问题。成功编译,没有报错的代码,真的就没有问题吗?
(2)这个答案肯定是否定的,不然也不会总是出现一些玄学问题。这里一样,我们这个代码从语法的角度,其实是不存在问题的,编译器是可以顺利通过的。所以,当我对这一串代码进行编译的时候,没有出现任何问题。
(3)但是,为什么我在装载驱动的时候,我的PC端就出现了报错呢?这个就需要介绍到,操作系统中的内存管理单元MMU了。
(4)
<1>MMU是计算机硬件中的一个组件,负责虚拟地址到物理地址的转换,以及对内存的访问权限控制。
<2>当程序执行时,它会请求内存分配,例如使用malloc()函数在堆上分配内存,或者定义局部变量在栈上分配内存。MMU负责跟踪这些内存分配,并记录哪些内存块已经被分配给了进程。
<3>内存管理通常通过内存映射来实现。每个进程都有自己的虚拟地址空间,该空间被分为不同的区域,例如代码段、数据段、堆、栈等。当程序请求内存时,操作系统会在虚拟地址空间中为该程序分配合适的虚拟内存地址。随后,MMU会将这些虚拟地址映射到物理内存地址。
<4>当程序试图访问某个虚拟地址时,MMU会将该虚拟地址转换为相应的物理地址。在此过程中,MMU会检查该虚拟地址是否位于有效的分配内存范围内,并且访问权限是否正确。如果虚拟地址是无效的或者权限不允许,MMU会触发一个异常(例如,段错误或访问违规),操作系统就会介入并终止程序的执行。
<5>所以,操作系统可以通过MMU来知道一块空间是否被申请使用,以及它的访问权限。任何试图访问未申请的内存或访问权限受限的内存的行为都会导致操作系统介入,并防止程序继续执行,从而确保了系统的稳定性和安全性。
(5)看了上面关于MMU的介绍,我们知道了,MMU可以阻止访问未被申请的内存或者权限访问受限的内存行为。这个就很好的说明了,为什么,这个bug有时候出现,有时候又消失的原因了。
(6)我们都知道,将gpios[i].name定义成字符指针的时候,他本质上是一个野指针,所以他指向的空间是否有效,是未知的。如果他指向了一个没有被申请的内存。就会显示段错误。
(7)但是,如果gpios[i].name作为字符指针,作为野指针指向的是一个已经被申请的内存,那么就不会发生段错了。但是,这样MMU的作用也显得没有那么大。真的是这样的吗?
(8)MMU发现这个野指针指向的是一个已经被申请的内存,但是,他能够识别这个野指针是否具有访问权限。如果没有访问权限,虽然不会报段错误,也依然会有其他报错出现。

没有MMU会怎么样

(1)由此可见,MMU极大的保护了系统的安全性。但是,我们上面都说了,MMU是计算机硬件的一个组件,如果我们当前使用的芯片,没有MMU,只是一个普普通通的微控制器,如STM32F103这种,会怎么样呢?
(2)因为没有MMU,所以常规的MCU是无法从硬件的角度来实现检测内存情况的。
(3)但是,真的就没有救了吗?显然不是,Linux现在支持没有MMU的芯片。所以,肯定还是有办法处理的。
(4)常见的软件内存管理方法有:位图管理链表管理内存池
(5)虽然存在软件的内存管理,但依然还是有缺陷的。因为没有硬件层面的地址转换和权限检查,这些方法可能会更容易受到错误、越界访问或资源争用等问题的影响。有MMU的系统能够更有效地隔离不同进程的内存空间,提供更好的安全性和稳定性。
(6)可能有人就会问了,为什么会更容易出现资源争用问题呢?依旧是拿我上面哪个报错的代码来举例子。
<1>首先,我们知道gpios[i].name定义成字符指针的时候,指向位置是未知的。那么就存在一个问题,假如gpios[i].name正好指向了一块被申请的,被其他变量占用的内存,会发生什么呢?
<2>这样我们如果对gpios[i].name进行数据调整,那么,对应的变量就会跟着改变。而按照正常逻辑来说,哪个变量应该是不会变的。那样就会引发未知的错误。
<3>这种野指针指向了一块其他变量存储区域的行为,就是资源争抢。

总结

(1)我们要清楚认识到,字符指针和字符数组指针的异同。如果字符指针没有被初始化,那么他就是一个危险的野指针。
(2)通过MMU机制,芯片能够进行很好的内存管理,来用于检测指针乱指向的问题。
(3)如果没有MMU机制,也可也通过位图管理链表管理内存池等方法进行内存管理,但是相比较有MMU而言,还是有所欠缺。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/797592.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JavaScript 07】函数声明 地位平等 函数提升 属性方法 作用域 参数 arguments对象 闭包 IIFE立即调用函数表达式 eval命令

函数 1 概述1.1 声明1.2 重复声明 1.3 圆括号/return/recursion1.4 一等公民1.5 函数提升 2 函数属性与方法2.1 name属性2.2 length属性2.3 toString() 3 函数作用域3.1 概念3.2 函数内部变量提升3.3 函数本身作用域 4 参数4.1 概念4.2 省略4.3 传递4.4 同名4.5 arguments 对象…

SSIS对SQL Server向Mysql数据转发表数据 (一)

开发工具 Visual Stuido 2019 、SSIS、SQL Server 2016、Mysql 8.0.30 1、配置VS2019的添加相应的功能&#xff0c;勾选SQL Server Data Tools,下载就行我用的VS2019版本还需要下载下面几个插件&#xff0c;链接我放在下面了 Microsoft Analysis Services Projects - Visual St…

城市内涝的原因有哪些?如何解决?

内涝是指由于强降水或连续性降水超过城市排水能力致使城市内产生积水灾害的现象。造成内涝的客观原因是降雨强度大&#xff0c;范围集中。降雨特别急的地方可能形成积水&#xff0c;降雨强度比较大、时间比较长也有可能形成积水。城市内涝的发生会引发交通瘫痪&#xff0c;甚至…

第二节 我用Python论证乖离率(BIAS)真的靠谱吗?

视频地址&#xff1a;点我查看文章配套视频&#xff0c;持续更新中~&#xff01; 什么是BIAS 乖离率也称为Y值&#xff0c;是用股价指数与移动平均线的比值关系来描述股票价格与移动平均线之间的偏离程度。乖离率指标是根据葛兰威尔八大买卖原则推演而来的&#xff0c;其原则是…

GPT4ALL私有化部署 01 | Python环境

进入以下链接&#xff1a; https://www.python.org/downloads/release/python-3100/ 滑动到底部 选择你系统对应的版本&#xff0c;如果你是win&#xff0c;那么大概率是win-64bit 有可能你会因为网络的问题导致下载不了&#xff0c;我提供了 链接 接着只需要打开 等待…

用于事实核查的知识图谱比较推理:问题定义和算法 7.24+7.26

用于事实核查的知识图谱比较推理&#xff1a;问题定义和算法 摘要介绍问题定义知识段&#xff08;Knowledge Segment KS&#xff09;共性不一致性集体共性集体不一致性成对比较推理集体比较推理 知识片段提取Predictate-Predictate Similarity特定边的知识段特定子图知识段 比较…

Vite构建的vue3项目修改网站标题和图标

1.准备一张.ico后缀的图片&#xff0c;这里推荐文件转换器&#xff0c;可以将常见的图片格式转为.ico格式图片。 2.修改网站标题和图标 网站的标题和图标都可以在项目根路径下的index.html下修改。 2.1 网站标题修改<title>标签体内容即可。 2.2 网站图标修改如图<…

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(8)-Fiddler如何设置捕获会话

1.简介 前边几篇宏哥介绍了Fiddler界面内容以及作用。今天宏哥就讲解和分享如何设置Fiddler后&#xff0c;我们就可以捕获会话&#xff0c;进行抓包了。 2.捕获会话的设备 常见的捕获会话的设备分为PC&#xff08;电脑&#xff09;端和手机&#xff08;Android和IOS苹果&…

【yolov8系列】将yolov8-seg 模型部署到瑞芯微RK3566上

前言 之前记录过【yolov5系列】将模型部署到瑞芯微RK3566上&#xff0c;整体比较流畅&#xff0c;记录了onnx转rknn的相关环境配置&#xff0c;使用的rk版本为rknn-toolkit2-v1.4.0。当前库已经更新为1.5&#xff0c;这里还是沿用1.4的版本进行记录。本篇博客是在上篇博客&…

重发布及路由策略

目录 重发布 作用 条件 规则 名词解释点 点 向 单点重发布 双点重发布 路由策略 控制层流量和数据层流量 抓流量 ACL列表 前缀列表( ip-prefix) 实例演示 做策略 过滤策略(过滤器-策略) 路由策略(route-policy) 基本配置 路由策略使用 配置实验 重发布 在…

Python 中一个好用的股票开源库akshare

背景 从小编真实接触股票已经有10年之久了&#xff0c;因为大学的专业就是数据与应用数据&#xff08;金融学方向&#xff09;&#xff0c;大三、大四学期时学习了很多涉及金融相关的课程&#xff0c;特别是在大四时&#xff0c;老师还专门给每位同学开通了模拟炒股的账户&…

合并 K 个升序链表——力扣23

题目描述 法一 顺序合并 class Solution { public:ListNode* mergeTwoLists(ListNode* l1, ListNode* l2){ListNode* dummy new ListNode(-1); //创建一个新的头节点 ListNode *curdummy, *aPtr l1, *bPtr l2;while(aPtr && bPtr){if(aPtr->val < bPtr->…

网银转账测试分析与设计

在银行项目面试中&#xff0c;面试官常问起网上银行转账功能如何测试&#xff0c;该问题既能考查面试者银行知识储备又能考查面试者的沟通表达能力。而很多人对于这个问题觉得很难回答&#xff0c;网上关于这块资料也并不多&#xff0c;特整理相关的测试点&#xff0c;抛砖引玉…

MyBatis学习笔记之逆向工程

文章目录 逆向工程配置与生成QBC查询风格 所谓的逆向工程是&#xff1a;根据数据库表逆向生成的Java的pojo类、SqlMapper.xml文件、以及mapper接口类等 要完成这个工作&#xff0c;需要借助别人写好的逆向工程插件。 虽然有点经典白学&#xff0c;但好像也没不白学 思考&#x…

数据结构入门指南:顺序表

目录 文章目录 前言 顺序表 静态顺序表 动态顺序表 总结 前言 今天我们正式进入对数据结构的学习&#xff0c;顺序表是数据结构中最简单的一种线性数据结构&#xff0c;也是数据结构入门的试金石&#xff0c;如果对于顺序表中内容理解过难&#xff0c;可以先填补一下C语言中结构…

ROS前驱前转小车仿真(2D)项目

文章目录 一.官方网址1.ROS官网2.urdf-模型3.rviz-数据可视化4.gazebo-仿真环境5.gmapping-建图6.navigation-导航 二.文件框架三.启动顺序0.依赖包的安装1.手动控制的启动顺序2.建图的启动顺序3.导航的启动顺序 四.urdf-模型文件1.ackermann.xacro-轮子传动的配置2.common_pro…

生信学院|07月28日《企业制造研发一体化解决方案》

课程主题&#xff1a;企业制造研发一体化解决方案 课程时间&#xff1a;2023年07月28日 14:00-14:30 主讲人&#xff1a;周可 生信科技 售前技术顾问 1、企业面临的挑战与痛点 2、达索系统研发制造一体化解决方案 3、DELMIAworks&#xff08;DMW&#xff09;制造运营管理价…

h3c m-lag简单配置案例

#SWA配置 [SWA]m-lag system-mac a08e-80d2-0100 #相同&#xff0c;建议选主设备为系统MAC [SWA]m-lag system-number 1 #主设备为1&#xff0c;备设备为2 [SWA]m-lag system-priority 123 #相同优先级 [SWA]m-lag keepalive ip destination 1.1.1.2 source 1.1.1.1 [SWA]int …

vue echarts实现根据选择项年月时间切换数据显示柱状图,vue页面监听自适应

echarts配置文档参考:Documentation - Apache ECharts 功能:可进行月度、年度切换显示相应的收入和支出柱状图数据; 这里进行了柱状图的简化配置,X轴Y轴都有所改写,具体的简化配置下文会贴出代码,参照功能开发时按照自己的需要去处理; 这里也会提到在开发时会遇到的问题…

两数相加 II——力扣445

题目描述 法一 栈 本题旨在从后往前加&#xff0c;为了逆序处理所有数位&#xff0c;利用栈&#xff0c;把数字压入栈中&#xff0c;再依次取出相加&#xff0c;注意进位&#xff01;进位是/10&#xff0c;另外需要注意栈的常用函数&#xff0c;push()、pop()、top()&#xff0…