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

前言

今天刷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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

信道编码的基本概念

本专栏包含信息论与编码的核心知识&#xff0c;按知识点组织&#xff0c;可作为教学或学习的参考。markdown版本已归档至【Github仓库&#xff1a;https://github.com/timerring/information-theory 】或者公众号【AIShareLab】回复 信息论 获取。 文章目录 信道编码信道编码的…

Spring,注解开发

Spring是一个轻量级的控制反转&#xff08;IOC&#xff09;和面向切面编程&#xff08;AOP&#xff09;的框架 1、组成 spring七大模块详解 2、IOC理论推导 传统的开发 (pojo层、DAO层和业务层&#xff09; &#xff08;1&#xff09;UserDao &#xff08;2) UserDaoImpl (3)…

CSS基础学习--5 background背景

一、介绍&#xff1a; CSS 背景属性用于定义HTML元素的背景。 CSS 属性定义背景效果: background-color 背景颜色background-image 背景图片background-repeatbackground-attachmentbackground-position 二、属性 2.1、background-color 属性定义了元素的背景颜色 <s…

位图以及布隆过滤器

本文主要讲解哈希思想的实际应用&#xff0c;位图和布隆过滤器。 位图 讲解位图之前我们先来解答这样一道腾讯的面试题 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中。【腾讯】 很多人立马就想到了用…

【零基础学机器学习 5】机器学习中的分类:什么是分类以及分类模型

&#x1f468;‍&#x1f4bb; 作者简介&#xff1a;程序员半夏 , 一名全栈程序员&#xff0c;擅长使用各种编程语言和框架&#xff0c;如JavaScript、React、Node.js、Java、Python、Django、MySQL等.专注于大前端与后端的硬核干货分享,同时是一个随缘更新的UP主. 你可以在各个…

Shell编程循环语句(for、while、until)

目录 一、for 循环 1.用法和特点 2.执行指定次数 3.遍历和迭代 &#xff08;1&#xff09;遍历 &#xff08;2&#xff09;迭代 4.操作实例 二、 while 循环 1.用法和特点 2.操作实例 三、until 循环 1.用法和特点 2.操作实例 一、for 循环 1.用法和特点 读取不…

【动态规划专栏】-- 01 背包问题 -- 动态规划经典题型

目录 背包问题概述 01 背包问题 01背包⭐⭐ 【算法原理】 第一问 第二问 C 算法代码 复杂度分析 【空间优化 - 滚动数组】 C 算法代码 复杂度分析 分割等和子集⭐⭐ 【算法原理】 对于类01背包问题 C 算法代码 【空间优化 - 滚动数组】 C 算法代码 目标和…

常见网络服务器并发模型

近些年&#xff0c;随着互联网的大发展&#xff0c;高并发服务器技术也快速进步&#xff0c;从简单的循环服务器模型处理少量网络并发请求&#xff0c;演进到解决C10K&#xff0c;C10M问题的高并发服务器模型。本文主要以TCP为例&#xff0c;总结了几种常见的网络服务器模型的实…

Java注解的入门学习

一、概念 Java注解是一种元数据形式&#xff0c;可以被添加到Java代码中的各种元素&#xff08;类、方法、字段等&#xff09;上&#xff0c;以提供关于这些元素的额外信息。注解是在Java 5中引入的一项特性&#xff0c;它们不直接影响代码的执行&#xff0c;而是提供了一种机…

本周大新闻|Vision Pro头显重磅发布;苹果收购AR厂商Mira

本周XR大新闻&#xff0c;上周Quest 3发布之后&#xff0c;本周苹果MR头显Vision Pro正式发布&#xff0c;也是本周AR/VR新闻的重头戏。 ​AR方面&#xff0c;苹果发布VST头显Vision Pro&#xff08;虽然本质是台VR&#xff0c;但以AR场景为核心&#xff09;以及visionOS&…

【三、网络配置与系统管理】

1 网络配置 ifconfig 显示网络接口的配置信息 [rootredis100 ~]# ifconfig ens33: flags4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 192.168.10.100 netmask 255.255.255.0 broadcast 192.168.10.255inet6 fe80::f5c3:6a96:fe05:1965 prefixlen 64 scop…

如何使用Docker实现分布式Web自动化!

1、前言 顺着docker的发展&#xff0c;很多测试的同学也已经在测试工作上使用docker作为环境基础去进行一些自动化测试&#xff0c;这篇文章主要讲述在docker中使用浏览器进行自动化测试如果可以实现可视化&#xff0c;同时可以对浏览器进行相关的操作。 如果你想学习自动化测…

畅聊趣坊项目测试报告

文章目录 项目背景项目功能测试计划与设计功能测试自动化测试 测试结果功能测试结果UI自动化测试结果 项目背景 在浏览网站时&#xff0c;发现好多网站开放出聊天的窗口&#xff0c;我们一发送消息就会收到一条消息&#xff0c;好奇这个功能是怎么实现的&#xff0c;最后查阅资…

cmake 基本使用

目录 CMake都有什么? 使用cmake一般流程为&#xff1a; 1 生成构建系统 使用命令在build外编译代码: cmake基本语法 指定使用最低版本的cmake 指定项目名称 指定生成目标文件的名称 指定C版本 cmake配置文件使用 cmake配置文件生成头文件 版本号定义方法一: 版本号定…

《操作系统》by李治军 | 实验6 - 信号量的实现和应用

目录 一、实验目的 二、实验内容 &#xff08;一&#xff09;用信号量解决生产者—消费者问题 &#xff08;二&#xff09;实现信号量&#xff0c;用生产者—消费者程序检验 三、实验准备 1、信号量 2、多进程共享文件 3、终端也是临界资源 4、原子操作、睡眠和唤醒 …

C++中string类的常用函数

文章目录 默认成员函数常见构造函数(constructor) string类的容量操作size()empty()capacity()reserve()clear()resize() string类对象的访问及遍历操作重载 [ ]begin()end()begin() end() 遍历字符串rbegin()rend()rbegin() rend()反向遍历字符串C11范围for string类对象修改…

广域网技术——ppp,pppoe

目录 PPP协议概述 PPP协议原理 PPP协议三大组件&#xff1a; PPP链路建立流程 PPP连接建立接口状态&#xff1a; LCP协议报文格式 PPP协议报文格式&#xff1a; 1&#xff0c;链路层建立连接过程 LCP协商过程-正常协商 LCP协商-参数不一致 LCP协商-参数不识别 2&#xf…

YOLOv5/v7 添加注意力机制,30多种模块分析③,GCN模块,DAN模块

目录 一、注意力机制介绍1、什么是注意力机制&#xff1f;2、注意力机制的分类3、注意力机制的核心 二、GCN 模块1、GCN 模块的原理2、实验结果3、应用示例 三、DAN模块1、DAN模块的原理2、实验结果3、应用示例 大家好&#xff0c;我是哪吒。 &#x1f3c6;本文收录于&#xf…

AMC12和高考数学哪个更难?知识点有哪些不同?

AMC12和高考数学哪个更难&#xff1f;知识点有哪些不同&#xff1f;今天小编给大家来详细介绍一下&#xff01; 难度对比 从难度上看&#xff0c;高考数学的计算量更大&#xff0c;并且知识点比AMC10/12超前&#xff0c;需要用到极限和微积分的知识。 反观AMC10/12不需要用到…

数据结构与算法之美 | 栈

栈结构&#xff1a;后进者先出&#xff0c;先进者后出 栈是一种“操作受限”的线性表 当某个数据集合只涉及在一端插入和删除数据&#xff0c;并且满足后进先出、先进后出的特性&#xff0c;这时我们就应该首选“栈”这种数据结构 栈的实现 使用数组实现&#xff1a;顺序栈…