动态内存管理详细讲解
目录
1.为什么存在动态内存分配
2. 动态内存函数的介绍
2.1 malloc和free
2.2 calloc
2.3 realloc
今天要和大家分享的内容是的动态内存管理,我们先从他的定义入手学习。
1.为什么存在动态内存分配
我们到现在已经掌握了内存开辟的方式就是要么创建一个变量,要么就创建一个数组
int a = 0;char arr[10] = { 0 };
如上所示,创建一个变量,就是在栈空间上开辟四个字节;创建一个char类型的数组里面有十个元素,就是在栈空间上开辟10个字节的连续的空间;
那我们目前学到的开辟空间的方法只有这两种方法;
这两种方法创建的空间大小是固定的,int类型就是四个字节,char类型的数组就是十个字节,不能将其增大也不能减小。所以这种方式在某些环境下是有一定的局限性的,所以为了让我们能更加灵活的控制我们所需要的内存的空间的大小,这时我们就需要学习C语言中动态内存管理的功能,
也会涉及到其中的一些相关的函数,接下来就对这些函数进行分析。
2. 动态内存函数的介绍
2.1 malloc和free
先在官方的网站上大概了解一下它的内容
malloc本质上是一个函数,使用时要包含<stdlib.h>的头文件,返回类型是人任意类型的指针,参数是 size_t类型,也就是无符号整形, 他的作用是在内存中申请数个字节的内存块,返回一个指针指向这个内存块的起始位置。
上代码简单使用一下这个函数
int main()
{int* p =(int*) malloc(20);return 0;
}
那么这段代码什么意思呢?
假设我们要开辟二十个字节的空间,我们就在malloc后面的括号中输入想要开辟的空间,注意单位是字节;
再来观察一下malloc函数的返回值,是一个任意类型的指针,我们在使用时要将其具体细化成我们想要的数据,那这里我们举一个例子,不妨将其定义为整形指针,所以也要给malloc函数开辟的空间的类型强制转化成int类型(我们所要使用的类型)
那以上就是malloc开辟空间的简单使用。
接下来在深度研究之前要了解一些知识
上图是我们计算机内存划分的简单的示意图,这里要为大家说明的是我们所创建的临时变量,和函数的形式参数以及具有临时性的变量都放在栈区;
我们今天索要讲解的动态内存管理的函数所申请的内存空间都在堆区中,可以看到上图有很多动态内存管理的函数,都会一一讲解;
最后就是静态区,静态区所存放的就是static所修饰的静态变量和全局变量;
了解完这些我们再回头看我们的malloc函数
我们使用malloc申请空间的时候要注意,malloc申请空间可能因为空间不足而导致申请失败,
而申请失败时就会返回一个空指针,所以我们在使用malloc函数时要对其进行判断;
代码如下
int main()
{int* p =(int*) malloc(20);if (p = NULL){printf("%s\n",strerro(errno));return 1;}
上面说过申请失败会返回一个空指针,我们不妨对其进行判断 :
如果p是空指针的话,就打印出他错误的原因,打印分析出错的原因后就利用return 1结束当前的程序,因为已经申请空间失败了,不能再往下走了,相信大家不难看懂
使用malloc函数申请空间后,要使用free来释放空间,
那free是怎样释放空间的呢?
可以看到free的函数的参数是一个任意类型的指针,也就是说使用free释放空间的时候,只需要将malloc申请的空间的首地址传进free函数中即可。
所以上面的代码中,malloc申请空间的首地址赋值给了指针变量p,所以我们将p传入free中即可
接下来将代码调试起来
可以看到malloc开辟的空间的首地址已经赋给了p;
这时free函数已经释放了p指针指向的空间,
但是这时我们要注意到是虽然空间已经得到了释放,但我们可以看到指针p指向了一块不知道的空间,这时p就成了一块野指针,所以我们要在最后将空指针赋予p
这时我们就看到p已经忘记了当时申请的20个字节的空间在哪
这时候就避免了野指针的问题;
申请空间和释放空间都研究过后我们再来看一看如何使用这块空间;
使用也非常的简单,既然我们申请的时一块连续的空间,我们不妨用数组来将其应用:
对申请的二十个空间进行访问我们可以利用数组的遍历对其访问,并将其打印出来以便我们观察
可以看到使用其申请的空间没有那么困难。
2.2 calloc
可以看到calloc函数的返回值是一个任意类型的指针,函数的两个参数都是size_t类型的数。
下面的对函数功能的描述是说开辟并且用'0'初始化数组。
用代码简单使用calloc函数:
int main()
{int* p = (int*)calloc(10, sizeof(int));if (p == NULL){printf("calloc()--%s", strerror(errno));return 1;}//使用int i = 0;for (i = 0; i < 10; i++){printf("%d ", *(p + i));}//释放free(p);p = NULL;return 0;}
可以看到使用对其开辟的空间时只是将其打印出来
运行的结果就是将其开辟的内容全都初始化为0;
那calloc和malloc有何区别呢?
1.参数不同
malloc只有一个参数,要开辟多少字节的空间直接在后面的括号内告诉他就好;
calloc有两个参数,要确定多少和一个数据多大的参数,类似于数组的开辟方式;
2.两者都是在堆区上申请空间,但是malloc不初始化,calloc会初始化为0;
如果要初始化就选择calloc,不需要初始化就选择malloc,具体要看需求使用 。
malloc在返回地址之前没有初始化,而calloc在返回地址之前要全部初始化为0,所以calloc的效率是比malloc要低的
2.3 realloc
继续观察官方网站对这个函数的定义
它的返回类型是任意类型的指针,函数的一个参数是任意类型的指针,另一个数size_t的无符号整型的整数;
对函数功能的描述就是改变内存块的大小
realloc函数的作用就是 让动态内存管理更加灵活。
有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时
候内存,我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小
的调整
我们直接用代码简单探究一下
我们可以看到这里再使用空间中增加了realloc的使用,这个意思就是说在指针p指向的首地址处,向后开辟40个字节的空间(注意这里开辟空间的字节大小要是加上之前空间的总大小)
使用这段空间也有两种方法,下面为大家用图例演示会更加便于理解
第一种情况:
这种增加内存的情况是在原先的内存空间中续上一段内存(篮筐表示realloc函数续上的内存)。这种情况下是因为本身申请的空间不会受到别的内存的干扰。
第二种情况:
上图这种情况时我们发现原本的空间后面,已经没有我们能够所再申请加长的空间了,这时候realloc就会重新申请一块更大的空间空间在别的地方,同时它会将之前空间的内容拷贝到新的空间中,这块空间一定满足你所开辟的空间,同时也会释放旧的空间,然后返回新空间的地址。
这就是realloc函数使用时内部会发生的情况;
但是要注意的是两种情况放回的地址不一样,第一种情况会返回旧的地址,第二种情况会返回新的地址。当然还要想到的一种情况可能会返回空指针,万一realloc在申请空间失败的情况下就会返回空指针,这点也必须考虑到,所以我们必须要用一个临时指针来存放他申请的空间,并且加以判断
使用例子如下
int*ptr=(int*)realloc(p, 40);if (ptr!=NULL){p = ptr;}else{printf("%s\n",strerror(errno));return 1;}
先使用realloc函数开辟空间,并将其首地址存入一个临时的指针变量,并加以判断,如果不是空指针,就交给原先的p指针对这块空间进行管理。
如果真的开辟空间失败的话,就结束当前进程。
那接下来就给大家调试起来,让大家看看是否真的会存放在不同的空间
我们可以看到两个指针的指向的地址是同样的,
那怎么样才会不一样呢?
我们只需要将realloc申请的空间增大
就可以看到两者的地址已经不一样了,这就是realloc在申请空间时的第二种情况。
以上就是索要分享的动态内存管理的函数的要分享的内容,下次会给大家分享常见的动态内存的错误。
如果这篇文章对你有所帮助,也请三连多多支持一下,感谢阅读。
相关文章:

动态内存管理详细讲解
目录 1.为什么存在动态内存分配 2. 动态内存函数的介绍 2.1 malloc和free 2.2 calloc 2.3 realloc 今天要和大家分享的内容是的动态内存管理,我们先从他的定义入手学习。 1.为什么存在动态内存分配 我们到现在已经掌握了内存开辟的方式就是要么创建一个变量…...

Python和Excel的完美结合:常用操作汇总(案例详析)
在以前,商业分析对应的英文单词是Business Analysis,大家用的分析工具是Excel,后来数据量大了,Excel应付不过来了(Excel最大支持行数为1048576行),人们开始转向python和R这样的分析工具了&#…...

卡特兰数、斯特林数基础
卡特兰数 从格点(0,0)(0,0)(0,0)走到格点(n,n)(n,n)(n,n),只能向右或向上走,不能穿过对角线,的路径的条数,称为卡特兰数HnH_nHn。 则有H01H_01H01。 通项公式: Hn(2nn)−(2nn−1)H_n\begin{pmatrix} 2n\\ n \en…...
STL——mapmultimap和setmultiset
一、关联式容器 与序列式容器相同,关联式容器也是用于存储数据的,不同的是,关联式容器里存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高。 二、键值对 用来表示具有一一对应的一种结构,该…...

2023热门抖音权重查询小程序源码
2023热门抖音权重查询小程序源码 跟抖音上很火的一模一样,小程序适配优化。接口免费。小程序不是网页 修改教程: 1,如果想修改或者去除水印,直接删除或修改“index.html”12~22行 2,如果想修改logo,直接…...

153.网络安全渗透测试—[Cobalt Strike系列]—[生成hta/exe/宏后门]
我认为,无论是学习安全还是从事安全的人多多少少都会有些许的情怀和使命感!!! 文章目录一、后门简介1、hta后门2、exe后门3、宏病毒后门二、生成后门并测试0、测试环境1、生成hta后门并测试2、生成exe后门并测试3、生成宏病毒后门…...

如何成为优秀的程序员
崔宝秋,现任小米首席架构师、小米云平台负责人。1995年赴美留学,纽约州立大学石溪分校计算机科学系博士毕业,曾任IBM高级工程师和高级研发经理、雅虎搜索技术核心团队主任工程师、LinkedIn主任工程师,2012年回国加入小米科技。 20…...

多线程(四):线程安全
在开始讲解线程安全之前我们先来回顾一下我们学了那些东西了: 1. 线程和进程的认识 2. Thread 类的基本用法 3. 简单认识线程状态 4. 初见线程安全 上一章结束时看了一眼线程安全问题,本章将针对这个重点讲解。 一个代码在单线程中能够安全执行&am…...

[ROC-RK3568-PC] [Firefly-Android] 10min带你了解Camera的使用
🍇 博主主页: 【Systemcall小酒屋】🍇 博主追寻:热衷于用简单的案例讲述复杂的技术,“假传万卷书,真传一案例”,这是林群院士说过的一句话,另外“成就是最好的老师”,技术…...
C++之模拟实现string
文章目录前言一、包含的相关头文件二、构造和析构1.构造函数2.拷贝构造1.传统写法2.现代写法3.赋值运算符重载1.传统写法2.现代写法4.析构函数三、iterator四、modify1.push_back(尾插一个字符)2.append(尾插一个字符串)3.运算符重载1.尾插字…...

SpringBoot实战(十三)集成 Admin
目录一、简介二、搭建 springboot-admin 管理服务1.Maven 依赖2.application.yml3.添加 EnableAdminServer4.启动服务,查看页面三、搭建 springboot-admin-client 客户端服务1.Maven 依赖2.application.yml3.启动服务,查看页面四、搭配 Eureka 使用1.搭建…...
mke2fs命令:建立ext2文件系统
以下内容源于网络资源的学习与整理,如有侵权请告知删除。 使用格式 mke2fs [options] [设备名称] [区块数] options与含义 -c:检查是否有损坏的区块。-F:不管指定的设备为何,强制执行mke2fs。-M:记录最后一次挂入的…...

免费分享一个springboot+vue的办公系统
springbootvue的OA系统项目介绍项目部署项目特点项目展示项目介绍 这是一个采用前后端分离开发的项目,前端采用 Vue 开发、后端采用 SpringBoot Mybatis 开发。 很适合java初学者练手和学习。 前端技术:Vue3.2 Vue-Router Pinia Ant Design Vue 3.X…...

STM32数据搬运工DMA
DMA的概念DMA,全称为:Direct Memory Access,即直接存储器访问。DMA 传输方式无需 CPU 直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路ÿ…...

4、操作系统——进程间通信(2)(system V-IPC介绍)
目录 一、system V-IPC常识 1、key和ID 2、文件描述符 3、函数(ftok) ftok产生IPC对象的健值key(类似文件路径) 4、例子 5、使用命令查看或删除当前系统中的IPC对象 一、system V-IPC常识 1、key和ID (1&#x…...

基于CentOS Stream 9平台搭建Nacos2.0.4集群以及OpenResty反向代理
目录展示Nacos2.0.4集群搭建1. 下载2. 解压3.修改配置3.1分别修改下启动类中JDK路径以及启动大小3.2 分别配置数据源3.3 创建nacos数据库3.4 修改cluster.conf配置3.4.1 复制并修改3.4.2 编辑文件,修改三台主机地址3.4.3 分别放入另外两个nacos的conf目录下:4. 启动…...
老杜MySQL入门基础 第二天
导入演示数据 1、连接MySQL 2、创建"bjpowernode"数据库 create database bjpowernode;3、选择数据库 use bjpowernode4、导入数据 source D:\bjpowernode.sql(文件的路径)1 去除重复记录(把查询结果去除重复记录)(原表数据不会改变) 使用关键字dist…...

Python深度学习实战:人脸关键点(15点)检测pytorch实现
引言 人脸关键点检测即对人类面部若干个点位置进行检测,可以通过这些点的变化来实现许多功能,该技术可以应用到很多领域,例如捕捉人脸的关键点,然后驱动动画人物做相同的面部表情;识别人脸的面部表情,让机…...

linux简单入门
目录Linux简介Linux目录结构Linux文件命令文件处理命令文件查看命令常用文件查看命令Linux的用户和组介绍Linux权限管理Linux简介 Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯本纳第克特托瓦兹࿰…...

给准备面试网络工程师岗位的应届生一些建议
你听完这个故事,应该会有所收获。最近有一个23届毕业的大学生和我聊天,他现在网络工程专业大四,因为今年6、7月份的时候毕业,所以现在面临找工作的问题。不管是现在找一份实习工作,还是毕业后找一份正式工作࿰…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...