第二十一章 (动态内存管理)
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 个常用的中间件,极大的提高了 …...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
