【C语言】动态内存管理------常见错误,以及经典笔试题分析,柔性数组【图文详解】

欢迎来CILMY23的博客喔,本篇为【C语言】动态内存管理------常见错误,以及经典笔试题分析,柔性数组【图文详解】,感谢观看,支持的可以给个一键三连,点赞关注+收藏。

前言

在了解完内存操作中最关键的一节---动态内存管理,了解malloc,realloc,calloc和free的用法后,我们将继续了解动态内存管理中常见错误,以及经典笔试题的分析和柔性数组。

 上一篇博客:

【C语言】内存操作篇---动态内存管理----malloc,realloc,calloc和free的用法【图文详解】

http://t.csdnimg.cn/rYlCo

目录

一、动态内存管理常见错误

 1.1对NULL指针的解引用操作

1.2对动态开辟空间的越界访问 

1.3 对非动态开辟内存使用free释放

1.4 使用free释放一块动态开辟内存的一部分 

1.5 对同⼀块动态内存多次释放

         1.6 动态开辟内存忘记释放(内存泄漏)

二、笔试题

2.1

2.2

2.3

2.4

三、柔性数组 


一、动态内存管理常见错误

 1.1对NULL指针的解引用操作

因为malloc,realloc和calloc它本身会返回地址,创建空间失败的时候会返回NULL,如果我们不对返回的地址进行检查,就可能存在free(NULL)的情况。

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

int main()
{
	int* p = (int*)malloc(10 * sizeof(int));

	*p = 20;

	free(p);
	p = NULL;
}

编译器会提示警告: 

 

1.2对动态开辟空间的越界访问 

开辟出来的空间仍然要保证自己不会越界访问

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

int main()
{
	int i = 0;
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("malloc");
	}
	for (i = 0; i <= 10; i++)
	{
		*(p + i) = i;//当i是10的时候越界访问
	}
	free(p);
	p = NULL;
}

需要检查代码防止越界访问

1.3 对非动态开辟内存使用free释放

int a = 10; 
int *p = &a; 
free(p);

 p并非是动态开辟出来的空间,所以是不能使用free的

1.4 使用free释放一块动态开辟内存的一部分 

	int i = 0;
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}
	for (i = 0; i <5; i++)
	{
		*p = i;
		p++;
	}
	free(p);
	p = NULL;

像上述代码p并非是动态开辟的空间中的起始位置,p不再指向动态内存的起始位置 

1.5 对同⼀块动态内存多次释放

	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}

	free(p);
	free(p);
	p = NULL;

我的程序会触发断点,因为我对p进行了多次的释放,最好的解决办法就是是释放一次就进行置空。 

 

  1.6 动态开辟内存忘记释放(内存泄漏)

void test()
{
	int* p = (int*)malloc(100); if (NULL != p)
	{
		*p = 20;
	}

	if (*p == 20)
	{
		return;
	}

	free(p);
	p = NULL;
}

int main()
{
	test();
}

当运行test的时候,会提前结束函数,所以p的指向空间就未知了,但是空间还是没有释放,最后会 造成内存泄漏,切记:动态开辟的空间⼀定要释放,并且正确释放。 

二、笔试题

2.1

运行以下代码Test会有什么结果?

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

void Test(void)
{
	char* str = NULL;
	GetMemory(str);
	strcpy(str, "hello world");
	printf(str);
}

程序运行结果如下:

 

 1.main中malloc申请的空间没有free

 2.strcpy对NULL解引用,导致程序崩溃

正确写法1: 

#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(str);
	free(str);
	str = NULL;
}

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

 程序结果如下:

 正确写法二:

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

char* GetMemory()
{
	char* p = NULL;
	p = (char*)malloc(100);
	return p;
}

void Test(void)
{
	char* str = NULL;
	str = GetMemory();
	strcpy(str, "hello world");
	printf(str);
	free(str);
	str = NULL;
}

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

 结果如下:

2.2

运行以下代码Test会有什么结果?

char* GetMemory(void)
{
	char p[] = "hello world";
	return p;
}
void Test(void)
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}

程序结果如下:

 

解析:

p出了函数作用域就销毁了,哪怕str指向了字符数组,由于函数在栈区被销毁,就不会存在了,所以打印不出hello world

 

2.3

 运行以下代码Test会有什么结果?

void GetMemory(char** p, int num)
{
	* p = (char*)malloc(num);
}

void Test(void)
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
}

运行结果如下:

 

解析:

没有free(str),str没有释放,会导致内存 泄漏 

2.4

运行以下代码Test会有什么结果?

void Test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);
	if (str != NULL)
	{
		strcpy(str, "world");
		printf(str);
	}
}

程序结果如下: 

 

 解析:

str在free后没有置空,成为了野指针,然后我们进行拷贝,编译器会提示我们使用了未初始化的内存。这题本质上考的还是free后有没有置空。

三、柔性数组 

也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的。C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。

例如:

typedef struct st_type
{
	int i;
	int a[0];//柔性数组成员
}type_a;

 有的编译器无法编译,可以改成:

typedef struct st_type
{
	int i;
	int a[];
}type_a;

3.1柔性数组的特点

结构中的柔性数组成员前面必须至少⼀个其他成员。
•    sizeof返回的这种结构大小不包括柔性数组的内存。
•    包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。 

 3.2柔性数组的使用

typedef struct st_type
{
	int i;
	int a[0];//柔性数组成员
}type_a;

int main()
{
	int i = 0;
	type_a* p = (type_a*)malloc(sizeof(type_a) + 10 * sizeof(int));

	p->i = 10;
	for (i = 0; i < 10; i++)
	{
		p->a[i] = i;
	}
	//缩短数组长度
	type_a* ptr = (type_a*)realloc(p, 15 * sizeof(int));
	if (ptr == NULL)
	{
		perror("realloc");
	}
	else
	{
		p = ptr;
		ptr = NULL;
	}

	free(p);
	p = NULL;
	return 0;
}

感谢各位同伴的支持,本期动态内存管理篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。  

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

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

相关文章

微信客户维护的三个关键点,助你提高转化率!

对于微信客户维护&#xff0c;有三个关键点尤为重要&#xff0c;它们能够有效提高客户转化率&#xff0c;让客户服务更加高效和个性化。接下来&#xff0c;让我们一起来了解这三个关键点。 1、 给客户打标签 在日常的客户维护中&#xff0c;给客户打标签是非常重要的。通过给…

BioTech - 药物晶型预测与剂型设计 概述

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/136441046 药物晶型预测与剂型设计是指利用计算机模拟和优化药物分子在固态形式下的结构、性质和稳定性&#xff0c;以及与制剂工艺和质…

【Python】外网远程登录访问jupyter notebook+pycharm使用ipython

第一步&#xff1a;创建python虚拟环境 conda create -n py3610 python3.6.10第二步&#xff1a;安装ipython pip install ipython pip install ipython notebook第三步&#xff1a;创建 IPython Notebook 服务器配置文件 # 进入python交互shell&#xff0c;设置密码 >&…

基于springboot+vue的校园失物招领系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

HLS的硬件加速器设计

完整可点击跳转 目录 硬件加速器的设计方法高层次综合HLSHLS与电路地对应关系HLS的设计规范HLS优化延迟优化降低单个循环的延迟循环展开(Unroll)循环展平(Flatten)多个循环的并行化循环合并循环函数化数据流执行(Dataflow)吞吐量优化循环/函数流水线数据流优化调试硬件加…

UCSF DOCK 分子对接详细案例(04)-基于RDKit描述符的分子从头设计DOCK_D3N

欢迎浏览我的CSND博客&#xff01; Blockbuater_drug …点击进入 文章目录 前言一、 软件及操作环境二、研究目的三、结构文件准备四、 DOCK/RDKit中 de novo design4.1 de novo design - refine_D3N4.2 对输出重新评分 总结参考资料 前言 本文是UCSF DOCK的使用案例分享&…

【JavaScript 漫游】【029】GlobalEventHandlers 接口总结

文章简介 本篇文章为【JavaScript 漫游】专栏第 029 篇文章&#xff0c;对 JavaScript 中的 GlobalEventHandlers 接口的知识点进行了总结。 GlobalEventHandlers 接口 除了 addEventListener()&#xff0c;还有一种方法可以直接指定事件的回调函数。 div.onclick clickHa…

LSA头部结构简述

LSA&#xff08;Link State Advertisement&#xff09;是一种用于路由协议头部结构&#xff0c;用于在网络中传递路由信息。 LSA头部结构包含以下几个字段&#xff1a; 1、LSA类型&#xff08;LSA Type&#xff09;&#xff1a;指示LSA的类型&#xff0c;不同类型的LSA用于传递…

软件项目概要设计说明书

1引言 1.1编写目的 1.2项目背景 1.3参考资料 2系统总体设计 2.1整体架构 2.2整体功能架构 2.3整体技术架构 2.4运行环境设计 2.5设计目标 3系统功能模块设计 3.1个人办公 3.2系统管理 4性能设计 4.1响应时间 4.2并发用户数 5接口设计 5.1接口设计原则 5.2接口实现方式 6运行设计…

【深度学习目标检测】二十一、基于深度学习的葡萄检测系统-含数据集、GUI和源码(python,yolov8)

葡萄检测在农业中具有多方面的意义&#xff0c;具体来说如下&#xff1a; 首先&#xff0c;葡萄检测有助于保障农产品质量安全。通过对葡萄进行质量安全专项监测&#xff0c;可以确保葡萄中的农药残留、重金属等有害物质含量符合标准&#xff0c;从而保障消费者的健康。同时&am…

Java 面试题

Java 基础 以下代码执行结果&#xff1f; 示例1&#xff1a; public static void main(String[] args) {int a 0;Integer b 0;String c "0";String d new String("0");change(a, b, c, d);System.out.println(a "|" b "|" …

springboot244基于SpringBoot和VUE技术的智慧生活商城系统设计与实现

智慧生活商城系统的设计与实现 摘 要 计算机网络发展到现在已经好几十年了&#xff0c;在理论上面已经有了很丰富的基础&#xff0c;并且在现实生活中也到处都在使用&#xff0c;可以说&#xff0c;经过几十年的发展&#xff0c;互联网技术已经把地域信息的隔阂给消除了&…

07.IO流

07. IO流 01. 文件 1. 什么是文件 ​ 文件对我们并不陌生&#xff0c;文件是保存数据的地方&#xff0c;比如大家经常使用的word文档&#xff0c;txt文件&#xff0c;excel文件…都是文件。它既可以保存一张图片&#xff0c;可以保存视频&#xff0c;声音 2.文件流 ​ 文件…

水牛社软件是真的吗?

软件是真的&#xff0c;不过毕竟是为了赚钱或者获取资源而买的&#xff0c;所以大部分只关心能赚多少钱吧 说实话&#xff0c;我用了2年了&#xff0c;一些独立的项目还有群&#xff0c;有一月挣几千上万的&#xff0c;有一月赚几百的 软件是一个集合体&#xff0c;不是像很多…

视频云平台——搭建SRS5平台支持GB28181视频流的推送

&#x1f4e2;欢迎点赞 &#xff1a;&#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff0c;赐人玫瑰&#xff0c;手留余香&#xff01;&#x1f4e2;本文作者&#xff1a;由webmote 原创&#x1f4e2;作者格言&#xff1a;新的征程&#xff0c;我们面对的不仅…

2核4g服务器能支持多少人访问?并发数性能测评

2核4g服务器能支持多少人访问&#xff1f;支持80人同时访问&#xff0c;阿腾云使用阿里云2核4G5M带宽服务器&#xff0c;可以支撑80个左右并发用户。阿腾云以Web网站应用为例&#xff0c;如果视频图片媒体文件存储到对象存储OSS上&#xff0c;网站接入CDN&#xff0c;还可以支持…

今晚打老虎:用katalon解决接口/自动化测试拦路虎--参数化

不管是做接口测试还是做自动化测试&#xff0c;参数化肯定是一个绕不过去的坎。 因为我们要考虑到多个接口都使用相同参数的问题。所以&#xff0c;本文将讲述一下katalon是如何进行参数化的。 全局变量 右侧菜单栏中打开profile&#xff0c;点击default&#xff0c;打开之后…

每天一道leetcode:20.有效的括号(简单;栈的经典题目)

⭐今日份题目 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有一个对…

算法沉淀——动态规划之完全背包问题(leetcode真题剖析)

算法沉淀——动态规划之完全背包问题 01.【模板】完全背包02.零钱兑换03.零钱兑换 II04.完全平方数 完全背包问题是背包问题的一种变体&#xff0c;与01背包问题不同&#xff0c;它允许你对每种物品进行多次选择。具体来说&#xff0c;给定一个固定容量的背包&#xff0c;一组物…

【DUSt3R】2张图2秒钟3D重建

【DUSt3R】2张图2秒钟3D重建 1. DUSt3R是一种用于稠密和无约束立体三维重建的方法,其实现步骤如下:2. 实际运行效果3. 运行结果4. 自问自答4.1 为社么这里要是使用transform模型呢?4.2 CroCo(通过跨视图完成3D视觉任务的自我监督预训练的一个研究)在DUSt3R的作用是什么,为…