C语言---形参所导致的段错误

news2024/10/6 10:40:20

前言

今天刷B站,无意之间看到一个宣称90%人都会错的嵌入式面试题。感兴趣就看了一下。卡了十多分钟才想明白,只是一个小知识点,但还是分享一下。

题目

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void getmemory(char *p)
{
	p = (char*)malloc(100);
}

void test(void)
{
	char *str = NULL;
	getmemory(str);
	strcpy(str,"hello world");
	printf("%s\n",str);
}

int main()
{
	test();
	return 0;
}

(1)我们看,上面这串代码有什么问题?其实是一个很简单的知识点,但是很容易让人卡住。
(2)如果想不出这串代码的问题,就直接运行试试。
(3)从运行结果上来看,进行的段错误报错。那么我们就需要知道段错误产生的可能原因:
<1>访问未分配的内存:当程序试图访问未经分配的内存区域时,例如使用未初始化的指针或指针越界访问数组,就会导致段错误。
<2>访问空指针:当程序试图访问一个空指针,即指向空地址的指针,而没有进行有效的空指针检查时,会导致段错误。
<3>内存越界访问:当程序试图访问超过数组边界范围的内存位置时,即访问了数组之外的内存,也会导致段错误。
<4>野指针:当程序使用已经释放的内存或已失效的指针时,就会产生野指针,进而导致段错误。
<5>内存对齐错误:某些体系结构要求访问特定数据类型的内存地址必须按照一定的对齐方式进行,如果违反了对齐要求,就会导致段错误。
<6>栈溢出:当程序递归调用层级过深或者使用过多的局部变量导致栈空间耗尽时,也可能引发段错误。
<7>其他异常情况:例如访问只读内存、在信号处理程序中发生错误等也可能导致段错误。

在这里插入图片描述

问题定位

(1)我们知道了段错误产生的可能性之后,开始定位可能的原因。
<1>访问未分配的内存,程序试图访问未经分配的内存区域:这个是存在可能的,因为getmemory()函数中,malloc函数可能没有分配区域。
<2>访问空指针:因为一开始初始化str为空指针,getmemory()函数中malloc函数可能没有返回给str。
<3>内存越界访问:malloc申请的是100个字节数据,而“hello world”一共才12个字节数据(注意,字符串末尾有‘\0’)。所以这个可能性比较小。
<4>野指针:这里虽然申请了内存,但是没有释放,所以可能性也比较小。
<5>内存对齐:这串代码没有内存对齐的内容。所以可能性也很小。
<6>栈溢出:这里才申请100字节的数据,溢出可能性比较小。
<7>访问只读内存什么的,这里也没有出现,所以可能性比较小。
(2)总结来看,有可能是malloc没有分配到内存导致的段错误,也有可能是malloc申请到了内存,但是没有将返回的数据传递给str。

判断malloc是否申请成功内存

(1)我们要判断malloc是否申请成功内存,于是我就打算将strcpy()函数放在getmemory()中即可。
(2)发现可以成功运行,所以malloc内存申请成功了。

在这里插入图片描述

判断是否是访问空指针的问题

(1)如果str为空指针,那么就会出现段错误,所以我就在getmemory()函数后面加上打印str中存放地址的参数。
(2)运行结果来看,发现str果然是空指针。

在这里插入图片描述

问题分析

(1)现在我们知道了,问题出现在str是一个空指针。那么为什么str会是一个空指针呢?
(2)这个就需要涉及到到函数的传参过程了。我们都知道,函数中传入的参数是一个形参。而形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。
(3)那么这就面临一个问题,malloc申请到了一个内存区域,这个区域首地址假设为0x3fff。返回给p之后,因为p是形参,所以函数结束之后,被释放,0x3fff这个值并没有传递到str中。
(4)下面是图解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如何更改

(1)知道形参的工作原理之后,就很好更改了。我们在传参的过程,可以使用二级指针。图解如下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)改为二级指针之后,我们还需要知道,每一次malloc申请内存,都要记得即使释放内存。所以我还增加了一个freememory()函数。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void getmemory(char **p)
{
	*p = (char*)malloc(100);
}

void freememory(char **p)
{
	free(*p);
	*p = NULL;
}

void test(void)
{
	char *str = NULL;
	getmemory(&str);
	strcpy(str,"hello world");
	printf("%s\n",str);
	freememory(&str);
}

int main()
{
	test();
	return 0;
}

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

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

相关文章

如何将bootloader和APP程序一次性烧录到单片机中

在做单片机的IAP升级时&#xff0c;通常需要两个程序&#xff0c;一个bootloader程序&#xff0c;一个app程序。首先将bootloader程序烧写到单片机中&#xff0c;然后通过串口将app程序写入到单片机内容&#xff0c;在平时学习和测试的时候这种方法没啥问题&#xff0c;但是如果…

K8S 生态周报| Ingress-NGINX v1.8 发布,升级前请先检查

“ 「K8S 生态周报」内容主要包含我所接触到的 K8S 生态相关的每周值得推荐的一些信息。欢迎订阅知乎专栏「k8s生态」[1]。 ” 大家好&#xff0c;我是张晋涛。 很抱歉&#xff0c;最近一段时间真的太忙了&#xff0c;写文章都断断续续的。主要在使用 Langchain 搭配 GPT-4 开发…

Nginx扩展篇之Location语法规则

1 Location语法规则 1.1 Location规则 语法规则&#xff1a; location [||*|^~] /uri/ {… } 首先匹配 &#xff0c;其次匹配^~,其次是按文件中顺序的正则匹配&#xff0c;最后是交给 /通用匹配。当有匹配成功时候&#xff0c;停止匹配&#xff0c;按当前匹配规则处理请求。 …

Nginx部署多个前端项目【Linux/Windows-详细操作】

需求:项目上线需要将前端的前台和后台部署在服务器上提供用户进行使用&#xff0c;部署在不同的服务器直接在服务器安装nginx即可。但是在内网安装还是有点麻烦&#xff0c;因为需要联网&#xff0c;如果是内网可以参考Linux安装Nginx并部署前端项目【内/外网-保姆级教程】_MXi…

将数组s中的每个元素的内容在原来的位置上重复n次numpy.char.multiply(s,n)

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将数组s中的每个元素的内容 在原来的位置上重复n次 numpy.char.multiply(s,n) 下列代码最后输出的结果是&#xff1f; import numpy as np x np.array([I, have, 2, cats]) print(&qu…

如何看待ICML2023的录用结果?

链接&#xff1a;https://www.zhihu.com/question/597314456 编辑&#xff1a;深度学习与计算机视觉 声明&#xff1a;仅做学术分享&#xff0c;侵删 作者&#xff1a;知乎用户 https://www.zhihu.com/question/597314456/answer/3000946712 不是因为文章被拒&#xff0c;而是因…

一文读懂 Mysql MVCC

&#x1f495;&#x1f495; 推荐&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; 文章目录 1、什么是 MVCC2、什么是当前读、快照读3、MVCC 具体解决什么问题4、MVCC 的实现原理4.1、4个隐式字段4.2、undo 日志4.3、Read View 5、使用 MVCC 时&#xff0c;需…

CSS灯光效果,背景黑金效果

先看效果 再看代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>灯光效果</title><link href"https://fonts.googleapis.com/css2?familyCinzel:wght700&amp;dis…

MyBatis 动态sql移除最后的逗号 mybatis trim标签用法 Mybatis 去掉最后的逗号符号

MyBatis 动态sql移除最后的逗号 mybatis trim标签用法 Mybatis 去掉最后的逗号符号 一、概述 在使用MyBatis 写动态sql时&#xff0c;经常会遇到要移除最后多余的 符号 &#xff0c;and &#xff0c; or之类的关键字 &#xff1b; 还有可能需要移除的前缀 where &#xff0c; s…

续-初识JAVaScript---(2)

初识JavaScript ———&#xff08;2&#xff09;&#xff01;&#xff01;&#xff01; 一、关于JavaScript中的数据类型 虽然在JS中的变量在声明的时候不需要指定数据类型&#xff0c;但是在赋值的时候&#xff0c;每一个数据还是有类型的&#xff0c;所以还是需要学习JS中…

c语言第一课---------它来了,它来了,带着薪资走来了

作者前言: 这是我的gitee仓库:https://gitee.com/qin-laoda/python-exercises 有兴趣的小可爱们可以点进去看看,里面有我写的代码我们一起来借鉴 由于本人的自我介绍已经自我介绍过了,在我的的第一篇博客里,有兴趣的小可爱可以去看看, 作者的建议 下面我们简单介绍学好C语言…

【Python】Python进阶系列教程-- Python3 JSON 数据解析(九)

文章目录 前言Python 编码为 JSON 类型转换对应表&#xff1a;JSON 解码为 Python 类型转换对应表&#xff1a;json.dumps 与 json.loads 实例 前言 往期回顾&#xff1a; Python进阶系列教程-- Python3 正则表达式&#xff08;一&#xff09;Python进阶系列教程-- Python3 C…

LLVM 标准 C++ 排序算法

Nature 官网发表《深度强化学习发现更快的排序算法》。 排序或散列这样的基本算法在任何一天都会被使用数万亿次1。随着计算需求的增长&#xff0c;这些算法的性能变得越来越重要 算法已经集成到 LLVM 标准 C排序库中&#xff0c;使用强化学习的新算法替换掉了原有的 LLVM libc…

STM32CubeMX | 44 - 使用GPIO点亮单总线RGBLED

一、单总线RGBLED 1. 硬件连接 在DragonFly上有四个全彩灯相连: 其中RGB_LED连接到STM32的PB9引脚。 2. 单总线通信协议 单总线通信协议中,表示bit0和bit1的码型如下: 时序值如下: 驱动一个单总线RGBLED只需要传输24bit颜色数据即可(MSB,高位优先),格式如下(注意…

OpenGL 冯氏光照模型

1.简介 现实世界的光照是极其复杂的&#xff0c;而且会受到诸多因素的影响&#xff0c;这是我们有限的计算能力所无法模拟的&#xff0c;冯氏光照模型的主要结构由3个分量组成&#xff1a;环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。下面这张图展示了这些光照分量看…

V4L2框架解析

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、概览二、流程简介三、关键结构体四、模块初始化五、处理用户空间请求 一、概览 相机驱动层位于HAL Moudle与硬件层之间&#xff0c;借助linux内核驱…

MacOS使用docker安装nginx

文章目录 一、docker安装nginx1、查看可用的nginx2、安装Nginx镜像3、查看是否安装成功4、安装成功后执行nginx5、查看容器6、本地验证 二、创建本地挂载文件1、第一步&#xff1a;宿主机创建目录2、第二步&#xff1a;将docker安装的nginx里面文件复制到宿主机3、第三步&#…

安洵杯2023wp - ukfc战队

喜提牛马第23名&#xff0c;不过对于我来说尽力了。 主方向逆向、密码学都极限输出了、但是第二道同模的题差一个点没想通&#xff0c;没得写很难受。 补题&#xff1a;NULL Web CarelessPy 目录 Web CarelessPy Confronting robot Reverse ez_cpp babythread 3D_m…

深入学习 Mysql 引擎 InnoDB、MyISAM

tip&#xff1a;作为程序员一定学习编程之道&#xff0c;一定要对代码的编写有追求&#xff0c;不能实现就完事了。我们应该让自己写的代码更加优雅&#xff0c;即使这会费时费力。 &#x1f495;&#x1f495; 推荐&#xff1a;体系化学习Java&#xff08;Java面试专题&#…

【数据结构与算法】 01 链表 (单链表、双向链表、循环链表、块状链表、头结点、链表反转与排序、约瑟夫环问题)

一、线性表1.1 概念与特点1.2 线性表的存储结构1.3 常见操作1.4 应用场景 二、链表2.1 链表简介2.2 单向链表&#xff08;单链表&#xff09;2.21 基本概念2.22 单链表基本操作2.23 C语言实现▶ 带头结点▶ 不带头结点 2.3 双向链表2.31 基本概念2.32 与单链表比较2.33 双向链表…