C语言的动态内存管理

news2024/12/30 3:13:16

目录

一、malloc函数

 二、free函数

三、calloc函数

四、realloc函数

五、realloc函数原地扩容和异地扩容测试

 六、动态内存管理的注意事项


一、malloc函数

1.头文件:stdlib.h(malloc.h)

2.函数原型:void * malloc(size_t size)

3.函数作用:按字节申请空间,申请成功返回申请空间的起始地址,申请失败返回NULL

4.测试代码:申请一块存放10个整型数据的空间(malloc返回值类型是void*,因此需要强转为所需类型)

int* a = (int*)malloc(sizeof(int) * 10);
if (a == NULL)
{
	perror("malloc fail");
    exit(-1);
}

如果申请空间为4 * INT_MAX则可能会申请失败,因为没有足够大的空间

int* a = (int*)malloc(sizeof(int) * INT_MAX * 4);
if (a == NULL)
{
	perror("malloc fail");
	exit(-1);
}

 二、free函数

1.头文件:stdlib.h

2.函数原型:void free(void * ptr)

3.函数作用:用于释放ptr指针指向的内存空间,该内存空间是由malloc、calloc、realloc函数在堆区申请的。

什么叫做释放内存空间?释放内存空间并不是清除内存空间的数据,而是将指向该内存空间的指针从内存管理系统的链表中删除,以便可以重新分配给其他内存空间使用(也就是将该内存空间的使用权还给操作系统)。指向该内存空间的指针就是malloc等函数的返回值,通常我们会将该指针赋值给一个新的指针变量,以便使用。

当内存空间被释放掉后,需要将用于接收申请得到的内存空间的地址的指针变量置为空,因为其所指向的内存空间使用权已经还给了操作系统,并且操作系统可能还将该内存空间分配给了其他程序,如果仍然使用该指针变量去操作那块内存空间,就可能会意外修改其他程序的数据。

4.测试代码:

下列代码使用malloc函数申请了4字节空间,并将该内存空间的指针赋值给指针变量a,用该内存空存放整型数据 1。最后将malloc申请的内存空间释放掉,并将指针变量a置为空。

int* a = (int*)malloc(sizeof(int));
if (a == NULL)
{
	perror("malloc fail");
	exit(-1);
}

*a = 1;
printf("%d\n", *a);

free(a);
a = NULL;

三、calloc函数

1.头文件:stdlib.h

2.函数原型:void * calloc(size_t num, size_t size)

3.函数作用:按字节申请空间,申请num个内存空间,每个内存空间占size个字节。申请成功返回申请空间的起始地址,申请失败返回NULL

calloc与malloc除了函数参数不同,calloc函数还会将申请得到的内存空间初始化为0

4.测试代码:

下列代码使用calloc函数申请了一块40个字节的内存空间,并将该空间初始化为0。

最后释放该内存空间,并将接收该内存空间地址的指针变量a置空

int* a = (int*)calloc(10, 4);
if (a == NULL)
{
    perror("calloc fail");
    exit(-1);
}
for (int i = 0; i < 10; i++)
{
    //a[i] = i;
    printf("%d ", a[i]);
}

free(a);
a = NULL;

四、realloc函数

1.头文件:stdlib.h

2.函数原型:void * realloc(void *ptr, size_t size)

3.函数作用:按字节扩容原有内存空间,ptr是原有申请空间,将该空间扩容到size字节大小,扩容成功返回扩容后空间的起始地址,扩容失败返回NULL

realloc如何扩容?

原地扩容:原内存空间后面的空间足够扩容,直接在原空间后追加扩容,返回原空间的起始地址

异地扩容:原内存空间后面的空间不够,重新找一块足够大的空间,将原空间的数据拷贝到新空间中,返回新空间的起始地址并将原空间释放掉

使用realloc函数扩容时,不能用原内存空间地址去接收,因为一旦扩容失败就会返回NULL,那么原内存空间的地址就会丢失。因此需要使用一个新的指针变量去接收,如果扩容成功再讲该指针变量赋值给接收原空间地址的指针变量。

4.测试代码:

下列代码先用calloc函数申请了一块40字节大小的内存空间,然后用realloc函数将原空间扩容到80字节。最后将内存空间释放掉,并将接收该内存空间地址的指针变量a置空

int* a = (int*)calloc(10, 4);
if (a == NULL)
{
    perror("calloc fail");
    exit(-1);
}

int* ptr = (int*)realloc(a, 80);
if (ptr != NULL)
{
    a = ptr;
}
else
{
    perror("realloc fail");
    exit(-1);
}

free(a);
a = NULL;

五、realloc函数原地扩容和异地扩容测试

1.原地扩容

观察监视窗口,还未进行扩容时,原内存空间的地址是0x000002881c1e9bc0

扩容后,新内存空间的地址仍然是0x000002881c1e9bc0,说明是原地扩容

2.异地扩容

 观察监视窗口,还未进行扩容时,原内存空间的地址是0x000001a8bcec9bc0

 观察监视窗口,扩容后,新地址空间是0x000001a8bd00e070,原空间与新空间的地址不一样,说明是异地扩容

 六、动态内存管理的注意事项

1.不做空间申请成功与否的判断,直接使用,会对进行NULL解引用

2.对非动态内存开辟的空间进行free释放

3.部分释放动态内存开辟的空间 

4.对同一块内存空间重复释放

 

如果释放完一次后先将a置为空,再释放就不会报错 

5.内存泄漏

对动态内存开辟的空间不释放且程序一直运行不退出,就会造成内存泄漏

例如下列代码中,main函数中一直调用test函数,而test函数中动态开辟的内存空间没有释放,main函数不停的调用test函数,程序又不会终止,因此该程序是在不停进行动态开辟内存空间但是不释放,这就是内存泄漏。

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

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

相关文章

春秋云境靶场CVE-2021-41402漏洞复现(任意代码执行漏洞)

文章目录 前言一、CVE-2021-41402描述二、CVE-2021-41402漏洞复现1、信息收集1、方法一弱口令bp爆破2、方法二7kb扫路径&#xff0c;后弱口令爆破 2、找可能可以进行任意php代码执行的地方3、漏洞利用找flag 总结 前言 此文章只用于学习和反思巩固渗透测试知识&#xff0c;禁止…

【ROS导航Navigation】五 | 导航相关的消息 | 地图 | 里程计 | 坐标变换 | 定位 | 目标点和路径规划 | 激光雷达 | 相机

致谢&#xff1a;ROS赵虚左老师 Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 参考赵虚左老师的实战教程 一、地图 nav_msgs/MapMetaData 地图元数据&#xff0c;包括地图的宽度、高度、分辨率等。 nav_msgs/OccupancyGrid 地图栅格数据&#…

shell脚本学习06(小滴课堂)

fi是结束循环的意思。 这里脚本1&#xff1a;代表着脚本和1.txt文件处于同一目录下。 脚本2为绝对路径的写法。 在使用./进行启动时&#xff0c;我们需要给文件赋予执行权限。 把文件名改为2.txt: 什么都没有返回&#xff0c;说明文件已经不存在。 可以使用脚本2 if else的方式…

48v变12v同步转换芯片

48v变12v同步转换芯片 以下是一篇关于48V变12V同步转换器WD5105ic的文章正文&#xff1a;48V变12V同步转换器WD5105ic是一种电源管理芯片&#xff0c;它可以将48V的直流电压转换为12V的直流电压。这款芯片具有广泛的应用范围&#xff0c;包括车载充电器件、电动车仪表器件、电…

【LabVIEW学习】2.for,while,事件

1.for实例&#xff08;随机输出数据100次&#xff09; 结果&#xff1a; 2.while实例&#xff08;i<50灯亮&#xff0c;大于之后灯灭&#xff09; 结果&#xff1a;&#xff08;先亮后灭&#xff09; 3.事件结构的实例&#xff08;点击按钮数据增加&#xff09;事件监听应该…

6.运行mysql容器-理解容器数据卷

运行mysql容器-理解容器数据卷 1.什么是容器数据卷2.如何使用容器数据卷2.1 数据卷挂载命令2.2 容器数据卷的继承2.3 数据卷的读写权限2.4 容器数据卷的小实验&#xff08;加深理解&#xff09;2.4.1 启动挂载数据卷的centos容器2.4.2 启动后&#xff0c;在宿主机的data目录下会…

reids管道

如何优化频繁命令往返造成的性能瓶颈&#xff1f; 如果同时需要执行大量的命令&#xff0c;那么就要等待上一条命令应答后再执行&#xff0c;这中间不仅仅多了RTT&#xff08;Round Time Trip&#xff09;&#xff0c;而且还频繁调用系统IO&#xff0c;发送网络请求&#xff0c…

SSM项目初始化流程与操作概念解释-SpringBoot简化版

文章目录 1.引入概念2.导入依赖3.项目配置4.依照SpringMVC框架构建项目 1.引入概念 例如某一个XX系统&#xff0c;该系统存在前台页面&#xff08;给用户直观看或使用&#xff09;&#xff0c;和后台页面&#xff08;给管理人员调整数据和权限&#xff09;。 这二个页面都通过…

QT自定义信号,信号emit,信号参数注册

qt如何自定义信号 使用signals声明返回值是void在需要发送信号的地方使用 emit 信号名字(参数)进行发送 在需要链接的地方使用connect进行链接 ct进行链接

pytorch.nn.Conv1d详解

通读了从论文中找的代码&#xff0c;终于找到这个痛点了&#xff01; 以下详解nn.Conv1d方法 1 参数说明 in_channels(int) – 输入信号的通道。 out_channels(int) – 卷积产生的通道。 kernel_size(int or tuple) - 卷积核的尺寸&#xff0c;经测试后卷积核的大小应为in_cha…

阅读记录【PMLR2023】The Aggregation–Heterogeneity Trade-off in Federated Learning

The Aggregation–Heterogeneity Trade-off in Federated Learning Abstract 机器学习的传统观点认为&#xff0c;训练模型的数据越多&#xff0c;模型的性能就越好。因此&#xff0c;人们开发了多种联邦学习方法来聚合尽可能多的本地样本。与这种观点相反&#xff0c;本文表…

字母不重复的子串-第15届蓝桥第二次STEMA测评Scratch真题精选

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第158讲。 第15届蓝桥第2次STEMA测评已于2023年10月29日落下帷幕&#xff0c;编程题一共有6题&#xff0c;分别如下&am…

2023年【化工自动化控制仪表】找解析及化工自动化控制仪表试题及解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 化工自动化控制仪表找解析参考答案及化工自动化控制仪表考试试题解析是安全生产模拟考试一点通题库老师及化工自动化控制仪表操作证已考过的学员汇总&#xff0c;相对有效帮助化工自动化控制仪表试题及解析学员顺利通…

openGauss学习笔记-125 openGauss 数据库管理-设置账本数据库-校验账本数据一致性

文章目录 openGauss学习笔记-125 openGauss 数据库管理-设置账本数据库-校验账本数据一致性125.1 前提条件125.2 背景信息125.3 操作步骤 openGauss学习笔记-125 openGauss 数据库管理-设置账本数据库-校验账本数据一致性 125.1 前提条件 数据库正常运行&#xff0c;并且对防…

【网络基础实战之路】基于不同协议间使用重发布路由策略

系列文章传送门&#xff1a; 【网络基础实战之路】设计网络划分的实战详解 【网络基础实战之路】一文弄懂TCP的三次握手与四次断开 【网络基础实战之路】基于MGRE多点协议的实战详解 【网络基础实战之路】基于OSPF协议建立两个MGRE网络的实验详解 【网络基础实战之路】基于…

威胜WFET2000s电能量数据采集终端-WF102协议报文解读

客户又追加需求了 要求把电表接入他们自己的管理系统 小头菜查找相关资料&#xff0c;发现威胜2000s采集终端功能挺多&#xff0c;但是售价比普通透传DTU贵了 N 倍。 迫于成本压力&#xff0c;小头菜和厂里负责管理系统的领导沟通&#xff0c;看能不能用普通DTU代替。 后来发现…

ACM练习——第四天

ok&#xff0c;今天又是三节课的一天。 刚刚吃完饭的我一刻也不敢耽误&#xff0c;直接开干&#xff01;&#xff01;&#xff01; 这些题和力扣上的&#xff0c;为了练习数据结构的题是不一样的。 直接上嘴脸 题目 第一次放学 (nowcoder.com)来自牛客网 思路 先看他的输入…

JavaScript 语句、标识符、变量

语句 JavaScript程序的单位是行(line),也就是一行一行地执行。一般情况下&#xff0c;每一行就是一个语句 var num 10; 语句以分号结尾&#xff0c;一个分号就表示一个语句结束。 标识符 标识符(identifier)指的是用来识别各种值的合法名称。最常见的标识符就是变量名标识符…

qt定时器的使用

在QWidget中进行声明

V10服务器安装virt-manage

kvm是什么 KVM(Kernel-based Virtual Machine, 即内核级虚拟机) 是一个开源的系统虚拟化模块。它使用Linux自身的调度器进行管理&#xff0c;所以相对于Xen&#xff0c;其核心源码很少。目前KVM已成为学术界的主流VMM之一&#xff0c;它包含一个为处理器提供底层虚拟化 可加载…