C语言中灵活多变的动态内存,malloc函数 free函数 calloc函数 realloc函数

文章目录
- 🚀前言
- 🚀管理动态内存的函数
- ✈️malloc函数
- ✈️free函数
- ✈️calloc函数
- ✈️realloc函数
- 🚀在使用动态内存函数时的常见错误
- ✈️对NULL指针的解引用
- ✈️ 对动态开辟空间的越界访问
- ✈️对非动态开辟内存使用free释放
- ✈️使用free释放一块动态开辟内存的一部分
- ✈️对同一块动态内存多次释放
- ✈️动态开辟内存忘记释放(内存泄漏)
🚀前言
铁子们好啊!今天阿辉给大家讲一下C语言里面特别重要的一块知识——动态内存管理,为什么说它重要呢?相信大家在使用数组时都遇到过数字开辟空间太大或者太小的情况,这是很尴尬的因为数组空间一旦确定就难以扩大或者缩小。而今天的动态内存管理将帮我们很好的解决这一窘境。话不多说,开始咱们今天的学习吧!!!
🚀管理动态内存的函数
动态内存的管理其实也就分为两块
- 空间的开辟和扩容
- 空间的释放
而要做到以上两点,我们要引入几个重要的管理动态内存的函数
动态内存的开辟和释放都是在堆区上
✈️malloc函数
malloc函数是用来开辟空间的,如何使用呢?下面是它的声明👇
void* malloc(size_t size);
关于malloc函数的注意事项:
size表示malloc函数所开辟空间的大小,单位是字节maloc函数对于开辟空间存放何种类型的数据并不关心,返回值是void*类型,malloc开辟空间成功,则返回这块空间的起始位置的地址;若开辟空间失败,则返回空指针NULL- 给
malloc传入的参数为0时,这种行为是C语言标准未定义的,取决于编译器 - 由
malloc函数开辟的空间,里面的内容是随机的
具体使用:
int mian()
{int* p = (int*)malloc(sizeof(int) * 10);//开辟10*4个字节的空间,返回值强转为int*if (p == NULL)//判断动态内存是否开辟成功{printf("malloc 开辟空间失败\n");//开辟失败返回调试语句,就是让程序员知道哪错了return 1;//开辟失败直接返回}//对动态开辟内存的进一步使用//这玩意其实就是个数组,有了首元素地址,不就是当成数组来玩嘛for (int i = 0; i < 10; i++)//十个元素初始化成0~9{p[i] = i;//这玩意与*(p+i) = i等价,不懂得可以看阿辉之前关于指针的文章}return 0;
}
关于malloc函数开辟的空间,它是一块连续的空间,直接当成数组使用一点毛病没有,
它与数组最大的区别在于,malloc开辟的空间是在堆区上的,而数组是在栈区上的。
而堆区上申请的空间须有程序员自己手动释放(Java,Python有垃圾回收机制),否则将造成内存泄漏。其实就是你从我这拿了空间去用,不用了就还给我,别占着茅坑不拉屎,你不用别人也用不了。对于堆区申请的空间的释放,这里要引入下面这个新的函数
✈️free函数
C语言提供了一个函数free,专门用来做动态内存的释放和回收的,函数声明如下:
void free(void* ptr);
对于free函数使用时的注意事项:
- 对于传给
free的参数必须是指向动态开辟内存(也就是是堆区开辟的空间)的起始地址的指针 - 若传给
free的参数是空指针NULL,free函数则什么也不干 free只会释放传入的指针指向的空间,并不会给传入指针置空,这会很危险,空间你都还给操作系统了,你这个指针还指向那里,这个指针很野得治,所以free完,指针我们要置空
int mian()
{//开辟动态空间int* p = (int*)malloc(sizeof(int) * 10);//判断动态内存是否开辟成功if (p == NULL){printf("malloc 开辟空间失败\n");return 1;}/*对动态开辟空间的使用*///不用啦,释放空间free(p);p = NULL;return 0;
}
👆这段代码就是动态内存的使用的基本模式,先开辟空间,然后判断是否开辟成功,接着使用这块空间,最后不用了把这块空间释放掉
✈️calloc函数
C语言中还提供了calloc函数,同样是进行动态内存分配的,函数声明如下:
void* calloc(size_t num, size_t size);
calloc与malloc仅有两点不同
- 使用上
calloc函数需要两个参数,开辟空间为num个大小为size个字节的空间 calloc函数开辟的空间会把每个字节全部初始化为0
int main()
{int* p = (int*)calloc(10, sizeof(int));if (p == NULL)//判断空间是否开辟成功{printf("calloc开辟空间失败\n");return 1;}for (int i = 0; i < 10; i++)//打印动态内存中的元素{printf("%d ", p[i]);}free(p);//空间释放p = NULL;//指针置空return 0;
}
输出:
0 0 0 0 0 0 0 0 0 0 //十个0
✈️realloc函数
铁子们估计有点不买账了,说好的动态内存分配,讲了这么多也没有体现动态俩字。铁子们别急,realloc函数才是今天的重头戏
C语言提供realloc函数用来使动态内存的使用更加灵活,之前开辟的空间太大或者太小都可以灵活的调整重新分配空间大小
realloc函数的函数声明
void* realloc(void* ptr,size_t size);
realloc函数在使用时要注意下面这几点:
-
ptr是要调整的空间的起始地址,ptr得是动态内存开辟的地址,若是ptr为空指针,realloc函数将与malloc函数的实现一样 -
size是realloc函数调整大小后的内存空间大小 -
realloc函数的返回值是空间调整后的起始地址,空间开辟失败返回空指针 -
realloc函数扩容的空间里面的值并未被初始化,是随机值 -
这个函数在调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间
-
对于
realloc函数调整空间有了两种情况:-
情况一:原有空间后有足够空间

-
情况二:原有空间后无足够空间,原有空间将被释放掉,重新找一块空间

-
例子:
int main()
{int* p = (int*)malloc(5 * sizeof(int));//先用malloc申请5个整型大小的内存空间if (p == NULL)//判断是否开辟成功{printf("malloc开辟空间失败\n");return 1;}int i = 0;for (i = 0; i < 5; i++){*(p + i) = 1;//把5个整型全部初始化为1}//不够用了,要再增加5个整型int* ptr = (int*)realloc(p, 10 * sizeof(int));if (ptr == NULL){printf("realloc开辟空间失败\n");return 1;}p = ptr;//空间扩容成功将ptr的地址赋给pptr = NULL;//ptr置空for (i = 0; i < 10; i++){printf("%d ", *(p + i));}free(p);p = NULL;return 0;
}
上述,使用realloc对空间做调整时,一定要新创建一个变量来接收realloc的返回值,因为如果使用指向原空间的起始地址的指针p来接收,一旦realloc开辟空间失败,p将被赋值成NULL,将找不到原来空间造成内存泄漏
🚀在使用动态内存函数时的常见错误
✈️对NULL指针的解引用
void test()
{int* p = (int*)malloc(INT_MAX / 4);*p = 20;//如果p的值是NULL,就会有问题free(p);
}
✈️ 对动态开辟空间的越界访问
void test()
{int i = 0;int* p = (int*)malloc(10 * sizeof(int));if (NULL == p){exit(EXIT_FAILURE);}for (i = 0; i <= 10; i++){*(p + i) = i;//当i是10的时候越界访问}free(p);
}
✈️对非动态开辟内存使用free释放
void test()
{int a = 10;int *p = &a;free(p);//error——不能对非动态内存进行释放
}
✈️使用free释放一块动态开辟内存的一部分
void test()
{int *p = (int *)malloc(100);p++;free(p);//p不再指向动态内存的起始位置
}
✈️对同一块动态内存多次释放
void test()
{int *p = (int *)malloc(100);free(p);free(p);//重复释放
}
✈️动态开辟内存忘记释放(内存泄漏)
void test()
{int *p = (int *)malloc(100);if(NULL != p){*p = 20;}
}
int main()
{test();while(1);
}
对于动态开辟的内存一定要记得释放,否则将造成内存泄漏
如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持博主,如有不足还请指点,博主及时改正,感谢大家支持!!!

相关文章:
C语言中灵活多变的动态内存,malloc函数 free函数 calloc函数 realloc函数
文章目录 🚀前言🚀管理动态内存的函数✈️malloc函数✈️free函数✈️calloc函数✈️realloc函数 🚀在使用动态内存函数时的常见错误✈️对NULL指针的解引用✈️ 对动态开辟空间的越界访问✈️对非动态开辟内存使用free释放✈️使用free释放一…...
小细节处理
重载运算符:重载<运算符。 bool operator<(const Edge&s)const{return w<s.w;}...
【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总
《博主简介》 小伙伴们好,我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推荐--…...
Python正则的匹配与替换
import re 查找时的注意事项,要查找的内容左右两边打出来,用真正的字符,不要用.*?,离查找内容远一点,再用.*? a /aksj<a>哈哈哈<a><p>拉阿鲁<p>\.askjp b re.findall(<a>(.*?)<…...
解决ELement-UI懒加载三级联动数据不回显(天坑)
最老是遇到这类问题头有点大,最后也是解决了,为铁铁们总结了一下几点 一.查看数据类型是否一致 未选择下 选择下 二.处理数据时使用this.$set方法来动态地设置实例中的属性,以确保其响应式 三.绑定v-if 确保每次重新加载 四.绑定key 五.完整代码...
【数据结构和算法】找出两数组的不同
其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 哈希类算法题注意事项 2.2 方法一:哈希法 三、代码 3.1 方法一:哈希法 四…...
基于Python的B站排行榜大数据分析与可视化系统
温馨提示:文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 本文介绍了一项基于Python的B站排行榜大数据分析与可视化系统的研究。通过网络爬虫技术,系统能够自动分析B站网址,提取大量相关文本信息并存储在系统中。通过对这些信息进行…...
MySQL一些常用命令
1、登录本地MySQL #一种是 mysql -u root -p; #(输入密码后回车)#另一种是 mysql -uroot -p123456; #(在-p后面直接带上密码)2、启动MySQL服务 net start mysql; 3、关闭MySQL服务: net stop mysql; 4、创建数据库 create database 数据库名; 5、创建数据…...
WPF 新手指引弹窗
新手指引弹窗介绍 我们在第一次使用某个软件时,通常会有一个“新手指引”教学引导。WPF实现“新手指引”非常方便,且非常有趣。接下来我们就开始制作一个简单的”新手指引”(代码简单易懂,便于移植),引用到我们的项目中又可添加一…...
py注册登录界面
代码分析 引入tkinter库,并从中导入messagebox模块。 read_users()函数用于读取存储用户信息的文本文件"users.txt"。它打开文件并逐行读取,将每行的用户名和密码以空格分隔后存储在一个列表中,最后返回该列表。 login(username,…...
基于电商场景的高并发RocketMQ实战-Consumer端队列负载均衡分配机制、并发消费以及消费进度提交
🌈🌈🌈🌈🌈🌈🌈🌈 【11来了】文章导读地址:点击查看文章导读! 🍁🍁🍁🍁🍁🍁dz…...
【Java开发岗面试】八股文—数据库MySQLRedis
声明: 背景:本人为24届双非硕校招生,已经完整经历了一次秋招,拿到了三个offer。本专题旨在分享自己的一些Java开发岗面试经验(主要是校招),包括我自己总结的八股文、算法、项目介绍、HR面和面试…...
IntelliJ IDEA [设置] 隐藏 .idea 等 .XXX 文件夹
文章目录 1. 问题描述2. 解决办法3. 最后效果4. 特殊处理(正常不需要此步骤)总结 我们使用 IntelliJ IDEA 导入项目的时候,经常会看到一些 .XXX 的文件夹(例如:.idea,.mvn,.gradle 等࿰…...
每日一题——LeetCode961
方法一 排序法: 2*n长度的数组里面有一个元素重复了n次,那么将数组排序,求出排序后数组的中间值(因为长度是偶数,没有刚好的中间值,默认求的中间值是偏左边的那个)那么共有三种情况:…...
基于Unity Editor开发一个技能编辑器可能涉及到的内容
基于Unity Editor开发一个技能编辑器,涉及到的方面较多,涵盖了Unity自身的GUI框架、序列化系统、自定义编辑器、脚本调用与数据存储等。下面是几个关键点和你可能会用到的类以及API: 自定义Inspector: 使用Editor类来重写组件的I…...
Ubuntu 22.04 安装ftp实现与windows文件互传
Ubuntu 22.04 安装ftp实现与windows文件互传 1、配置安装 安装: sudo apt install vsftpd -y使能开机自启: sudo systemctl enable vsftpd 启动: sudo systemctl start vsftpd创建ftp工作目录: sudo mkdir -p /home/ftp/uftp…...
EasyPoi使用案例
EasyPoi使用案例 easypoi旨在简化Excel和Word的操作。基于注解的导入导出,修改注解就可以修改Excel;支持常用的样式自定义;基于map可以灵活定义表头字段;支持一对多的导入导出;支持模板的导出;支持HTML/Exc…...
分布式系统架构设计之分布式数据存储的分类和组合策略
在现下科技发展迅猛的背景下,分布式系统已经成为许多大规模应用和服务的基础架构。分布式架构的设计不仅仅是一项技术挑战,更是对数据存储、管理和处理能力的严峻考验。随着云原生、大数据、人工智能等技术的崛起,分布式系统对于数据的高效存…...
javaEE -18(11000字 JavaScript入门 - 3)
一:事件 (高级) 1.1 注册事件(绑定事件) 给元素添加事件,称为注册事件或者绑定事件,注册事件有两种方式:传统方式和方法监听注册方式 传统注册方式 : 利用 on 开头的…...
LangChain.js 实战系列:入门介绍
📝 LangChain.js 是一个快速开发大模型应用的框架,它提供了一系列强大的功能和工具,使得开发者能够更加高效地构建复杂的应用程序。LangChain.js 实战系列文章将介绍在实际项目中使用 LangChain.js 时的一些方法和技巧。 LangChain.js 是一个…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
