动态内存管理详细讲解
目录
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月份的时候毕业,所以现在面临找工作的问题。不管是现在找一份实习工作,还是毕业后找一份正式工作࿰…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
