第二十一章 (动态内存管理)
1. 为什么要有动态内存分配
2. malloc和free
3. calloc和realloc
4. 常⻅的动态内存的错误
5. 动态内存经典笔试题分析
6. 总结C/C++中程序内存区域划分
1.为什么要有动态内存管理
我们目前已经掌握的内存开辟方式有
int main()
{int num = 0; //开辟4个字节int arr[10] = { 1,2,3,4,5,6 };return 0;
}
但是上边的开辟空间的方式有两个特点
1.空间开辟大小是固定的。
2. 数组在申明的时候,必须指定数组的长度,
数组空间一旦确定大小就不能调整
解决方法:

二、malloc和free
2.1 malloc
c语言提供了一个动态内存开辟的函数:

这个函数向内存申请的是一块连续可用的空间,并返回指向这块空间的指针
1.开辟成功,则返回一个指向开辟好空间的指针
2.开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查
3.返回类型的是void * ,所以malloc函数并不知道开辟空间的类型,具体在使用者使用的时候自己来选择
4.如果参数size为0,malloc函数的行为标准是为定义的,取决于编译器。
2.2 free
c 语言还提供了另一个函数free,是专门用来做动态内存的释放和回收的(一般是要与malloc函数同时使用的),函数原型如下

1.如果参数ptr指向的空间不是动态开辟的,那么free函数是为定义的
2.如果参数ptr函数是NULL的话,则函数不需要做任何事
malloc 和free都在stdlib.h头文件中
#include<stdio.h>
#include<string.h>
#include<stdlib.h>int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int ret = sizeof(arr) / sizeof(arr[0]);int* ptr = NULL;ptr=(int *)malloc(ret * sizeof(int)); //开辟内存if (ptr != NULL){for (int i = 0; i < ret; i++){*(ptr + i) = i;printf("%d ", *(ptr + i));}}free(ptr); //释放内存ptr = NULL; //这一步是否有必要?//(这里的作用是防止如果再次使用ptr进行判断,可以避免进行的访问)return 0;
}
这里我们来画图解释一下

三、calloc和recallo
除了malloc函数以外c语言还提供了另外一个函数calloc函数,calloc函数也可以用来进行动态内存的分配。原型如下:

1.函数的功能是为num个大小为size的元素开辟一块空间,并且把每个字节初始化为。
2.与malloc函数的区别只在与calloc会在返回地址之前把申请的空间的每个字节初始化为全0.
int main()
{int* pr = (int*)calloc(10, sizeof(int));if(pr!=NULL){for (int i = 0; i < 10; i++){printf("%d " ,*(pr+i));}}free(pr);pr = NULL;return 0;
}

这里我们可以知道如果我们想对申请的空间进行初始化的时候,就可以使用calloc函数来解决。
3.2
realloc函数的出现让动态内存的管理更加灵活。
- 在有些情况下我们会发现申请的空间会过大或者过小,这时候我们就可以用realloc函数来对我们开辟内存的大小进行调整。

这里我们来解释一下
1.ptr是要调整的内存地址
2.size是调整之后新大小
注意这个函数是在原有的内存大小的基础上,将原来的数据移动到新的空间中
3.realloc在调整内存空间是存在两种情况的
3.1 原有的空间有足够大的空间情况
3.2 原有空间之后没有足够大的空间

情况1
当是情况1 的时候,要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发⽣变化。
情况2
当是情况2 的时候,原有空间之后没有⾜够多的空间时,扩展的⽅法是:在堆空间上另找⼀个合适⼤⼩的连续空间来使⽤。这样函数返回的是⼀个新的内存地址
由于这两种情况我们再使用realloc函数的时候就需要多注意一下
int main()
{int* ptr = (int*)malloc(25 * sizeof(int)); //这里是100个字节if (ptr != NULL){for (int i = 0; i < 50; i++){*ptr = i;printf("%d ", *ptr);}}//那么如果我们想要更大的内存呢?//int* ptr = realloc(ptr, 1000);//这种写法是有问题的,如果我们开辟了一块新的内存之后,还这样用那么可能就会导致访问的失败int* p = realloc(ptr, 1000);//用这种方式是最好的if (p != NULL) //判断如果p是不为空的话{ptr = p; // 把新地址赋给ptr,我们就可以使用ptr来操作新地址}free(ptr);ptr = NULL;return 0;}
四、常见的动态内存的错
这里我们来举几个例子
1.
void test(){int *p = (int *)malloc(INT_MAX/4);*p = 20;//如果p的值是NULL,就会有问题free(p);}
这个是没有判断指针是否为NULL的情况
2.越界访问
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);}
void test()
{int a = 10;int* pr = &a;*pr = 10;free(pr); //对非动态内存地址进行释放pr = NULL;
}int main()
{test();return 0;
}
void test()
{int* p = (int*)malloc(10 * sizeof(int));p++;free(p); //释放的位置不是起始位置return 0;
}int main()
{test();return 0;
}
void test(){int* p = (int*)malloc(10 * sizeof(int));free(p);free(p); //多次释放return 0;}int main(){test();return 0;}
void test()
{int i = 0;int* p = (int*)malloc(10 * sizeof(int));if (NULL == p){exit(EXIT_FAILURE);}for (i = 0; i <= 9; i++){*(p + i) = i;//当i是10的时候越界访问printf("%d ", *(p + i));}//没有释放内存,可能会导致内存泄露
}int main(){test();return 0;}
void GetMemory(char* p)
{p = (char*)malloc(100);//没有返回值
}
void Test(void)
{char* str = NULL;GetMemory(str);//这里的函数值没有接收,所以并没有什么用strcpy(str, "hello world"); //所以这里的str为0printf(str);
}int main()
{text();return 0;
}
该代码会报错
void Test(void)
{char* str = (char*)malloc(100); //这里没有判断是否为0strcpy(str, "hello");free(str); //释放空间后没有置为0,可能就会导致内存泄露if (str != NULL){strcpy(str, "world");printf(str);}
}int main()
{Test();return 0;
}
六、总结c/c++中程序内存区域划分
1、栈区:在执行函数的时候,函数内的局部变量的储存单元都可以在栈上创建,函数执行结束的时候这些储存单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率高,但是分配的内存容量有限。栈区主要分配的是局部变量、函数参数、返回数据、返回地址等。
2.堆区:一般由程序员分配释放,如果程序员不释放,程序结束的时候可能由os来释放。分配方式类似于链表
3.数据段(静态区):(static)存放全局变量、静态数据。程序结束后由系统释放。
4. 代码段:存放函数体(类成员函数和全局变量)的二进制代码。
相关文章:
第二十一章 (动态内存管理)
1. 为什么要有动态内存分配 2. malloc和free 3. calloc和realloc 4. 常⻅的动态内存的错误 5. 动态内存经典笔试题分析 6. 总结C/C中程序内存区域划分 1.为什么要有动态内存管理 我们目前已经掌握的内存开辟方式有 int main() {int num 0; //开辟4个字节int arr[10] …...
机器学习框架总结
机器学习框架是用于构建、训练、评估和部署机器学习模型的工具和库的集合。它们简化了模型开发过程,并提供了预构建的功能、优化的计算性能和对深度学习、监督学习、无监督学习等技术的支持。下面是一些主要的机器学习框架的详细介绍: 1. TensorFlow 1…...
docker pull 超时的问题如何解决
docker不能使用,使用之前的阿里云镜像失败。。。 搜了各种解决方法,感谢B站UP主 <iframe src"//player.bilibili.com/player.html?isOutsidetrue&aid113173361331402&bvidBV1KstBeEEQR&cid25942297878&p1" scrolling"…...
【数学分析笔记】第4章第3节 导数四则运算和反函数求导法则(2)
4. 微分 4.3 导数四则运算与反函数求导法则 双曲正弦函数 sh x e x − e − x 2 \sh x\frac{e^x-e^{-x}}{2} shx2ex−e−x 双曲余弦函数 ch x e x e − x 2 \ch x\frac{e^xe^{-x}}{2} chx2exe−x ch 2 x − sh 2 x 1 \ch^2 x-\sh^2 x1 ch2x−sh2x1 ( e…...
【2024】基于mysqldump的数据备份与恢复
基于mysqldump备份与恢复 mysqldump是一个用于备份 MySQL 数据库的实用工具。 它可以将数据库的结构(如数据库、表、视图、存储过程等的定义)和数据(表中的记录)导出为文本文件,这些文本文件可以包含 SQL 语句&#…...
家用无线路由器配置
一.首先进行线路连接。如下图:"光猫LAN口"—网线—"路由器WAN口"。 注意:家用光纤宽带一般选择使用200兆宽带到1000兆,如果网速不达标请查看路由器是否是千兆路由器。千兆路由器通常是双频的,支持两个信号一个…...
模拟算法(4)_外观数列
个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 模拟算法(4)_外观数列 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论💌 目录 1. 题目链…...
vsomeip用到的socket
概述: vsomeip用到的socket的代码全部都在implementation\endpoints目录下面,主要分布在下面六个endpoint类中: local_client_endpoint_impl // 本地客户端socket(UDS Socket或者127.0.0.1的socket)local_server…...
MFC有三个选项:MFC ActiveX控件、MFC应用程序、MFC DLL,如何选择?
深耕AI:互联网行业 算法研发工程师 目录 MFC ActiveX 控件 控件的类型 标准控件 自定义控件 ActiveX控件 MFC ActiveX控件 标准/自定义控件 MFC ActiveX控件分类 3种MFC如何选择? MFC ActiveX控件 MFC 应用程序 MFC DLL 总结 举例说明…...
边缘概率 | 条件概率
关于什么是边缘概率分布和条件概率分布,在理论上,我自己也还没有理解,那么现在就根据我学习到的理解方式来记录一下,有错误指出,请大家指正!!! 例如,一个箱子里有十个乒乓…...
深入浅出:现代JavaScript开发者必知必会的Web性能优化技巧
亲爱的读者们,欢迎来到本期博客。今天,我们将深入探讨JavaScript开发者在日常工作中如何提升Web性能。在快节奏的Web开发世界中,性能优化至关重要。本文将分享一些实用技巧,帮助你构建快速、高效的Web应用。 1. 使用CDN加速资源加…...
【S32K3 RTD LLD篇5】K344 ADC SW+HW trigger
【S32K3 RTD LLD篇5】K344 ADC SWHW trigger 一,文档简介二,ADC SW HW 触发2.1 软硬件平台2.2 SWADC 软件触发2.3 SWBCTUADC 软件BCTU触发2.4 PITTRIGMUXADC 硬件PIT TRIGUMX触发2.5 EMIOSBCTUHWADC硬件EMIOS BCTU触发2.6 EMIOSBCTUHW LISTADC硬件EMIOS …...
TransFormer 视频笔记
TransFormer BasicsAttention单头注意力 single head attentionQ: query 查寻矩阵 128*12288K key matrix 128*12288SoftMax 归一 Value matrix 12288*12288 MLP Bas…...
前端的混合全栈之路Meteor篇(三):发布订阅示例代码及如何将Meteor的响应数据映射到vue3的reactive系统
Meteor 3.0 是一个功能强大的全栈 JavaScript 框架,特别适合实时应用程序的开发。它的核心机制之一就包括发布-订阅(Publish-Subscribe)模型,它允许服务器端发布数据,客户端订阅并实时更新。本文将介绍如何在 Meteor 3…...
自动驾驶系列—颠覆未来驾驶:深入解析自动驾驶线控转向系统技术
🌟🌟 欢迎来到我的技术小筑,一个专为技术探索者打造的交流空间。在这里,我们不仅分享代码的智慧,还探讨技术的深度与广度。无论您是资深开发者还是技术新手,这里都有一片属于您的天空。让我们在知识的海洋中…...
Webstorm 中对 Node.js 后端项目进行断点调试
首先,肯定需要有一个启动服务器的命令脚本。 然后,写一个 debug 的配置: 然后,debug 模式 启动项目和 启动调试服务: 最后,发送请求,即可调试: 这几个关键按钮含义: 重启…...
VUE前后端分离毕业设计题目项目有哪些,VUE程序开发常见毕业论文设计推荐
目录 0 为什么选择Vue.js 1 Vue.js 的主要特点 2 前后端分离毕业设计项目推荐 3 后端推荐 4 总结 0 为什么选择Vue.js 使用Vue.js开发计算机毕业设计是一个很好的选择,因为它不仅具有现代前端框架的所有优点,还能让你专注于构建高性能、高可用性的W…...
一、Spring Boot集成Spring Security之自动装配
Spring Boot集成Spring Security之自动装配介绍 一、实现功能及软件版本说明二、创建Spring Boot项目三、查看自动装配配置类四、自动装配配置类之SecurityAutoConfiguration1、SecurityAutoConfiguration部分源码2、主要作用3、SpringBootWebSecurityConfiguration3.1、Spring…...
计数相关的题 Python 力扣
2284. 最多单词数的发件人 给你一个聊天记录,共包含 n 条信息。给你两个字符串数组 messages 和 senders ,其中 messages[i] 是 senders[i] 发出的一条 信息 。 一条 信息 是若干用单个空格连接的 单词 ,信息开头和结尾不会有多余空格。发件…...
Express内置的中间件(express.json和express.urlencoded)格式的请求体数据
目录 Express内置的中间件 express.json 中间件的使用 express.urlencoded 中间件的使用 express.urlencoded([options]) 解析req.body的兼容写法 Express内置的中间件 自 Express 4.16.0 版本开始,Express 内置了 3 个常用的中间件,极大的提高了 …...
新手程序员必备:收藏这份Prompt指南,轻松驾驭大模型创造业务价值!
本文系统介绍了大模型Prompt的概念、撰写框架及核心原则,深入剖析了构建高质量Prompt的实操方法。从RTF、思考链到RISEN等五大框架,再到提升Prompt效果的策略,如明确指令、结构化输出、赋予模型思考时间等,帮助读者高效驾驭大模型…...
【实战指南】League Akari:英雄联盟智能工具全解析
【实战指南】League Akari:英雄联盟智能工具全解析 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 一、价值定位:重新定…...
开源工具:IDM Activation Script彻底解决激活弹窗问题的技术方案
开源工具:IDM Activation Script彻底解决激活弹窗问题的技术方案 【免费下载链接】IDM-Activation-Script IDM Activation & Trail Reset Script 项目地址: https://gitcode.com/gh_mirrors/id/IDM-Activation-Script Internet Download Manager…...
AirPods Pro 3 与 Bose QC Ultra Earbuds 2:无线耳机市场的激烈较量
AirPods Pro 3 与 Bose QC Ultra Earbuds 2:新功能大比拼最新款的 AirPods Pro 3 引入了一系列新功能,提升了音频效果,增强了降噪能力,还具备助听模式、实时翻译、自动切换、空间音频、心率监测等附加功能。而 Bose QuietComfort …...
AugmentCode无限续杯插件:突破登录限制的自动化解决方案
AugmentCode无限续杯插件:突破登录限制的自动化解决方案 【免费下载链接】free-augment-code AugmentCode 无限续杯浏览器插件 项目地址: https://gitcode.com/gh_mirrors/fr/free-augment-code 痛点解析:开发者的账户管理困境 在软件开发与测试…...
学习神经网络
一、神经网络概述:人工智能的核心基石(一)神经网络的定义与起源神经网络,全称为人工神经网络(Artificial Neural Network,ANN),是一种模仿生物神经网络(动物大脑神经元网…...
CANoe Trace中的Time列:从基础定义到高级时序分析实战
1. CANoe Trace中的Time列基础解析 第一次打开CANoe的Trace窗口时,那排密密麻麻的数据确实让人头皮发麻。但别担心,咱们先来搞定最左边那个看似简单却至关重要的Time列。这个时间戳就像车载网络的"心电图"记录仪,精确到微秒级别地记…...
郭老师-最高级的活法:不渡无缘之人
最高级的活法 ——不干涉他人的因果“说教只会引来仇恨, 疼痛才是最好的老师。”🌿 真正的慈悲, 不是拉人上岸, 而是—— 允许他沉下去,再自己浮起来。⚖️ 一、四大悲哀:强行渡人,反被拖下水行…...
项目管理和技术管理的区别
在单位从事管理岗快2年了,负责单位内的研发项目管理和技术管理工作。感觉这是两个不同的管理赛道。其中项目管理侧重进度、资源、风险、责任人、排期等要素推进和汇报。技术管理则侧重研发环节的技术深度、技术方向、技术领先性、技术栈,以及项目产出的质…...
长上下文与RAG
读到一篇探讨RAG技术的文章,很受用,遂记录一下。核心结论:RAG不会被无限上下文取代。 原文地址:LLM无限上下文了,RAG(Retrieval Augmented Generation)还有意义吗? - 今日头条 以下…...
