C / C++内存管理

news2024/9/21 18:37:29

内存分布

1. 栈又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。

2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共 享内存,做进程间通信,子进程堆区的开辟。

3. 堆用于程序运行时动态内存分配,堆是向上增长的。

4. 数据段--存储全局数据和静态数据。

5. 代码段--可执行的代码/只读常量。

在C和C++中我们的函数内变量都是存在于栈上的,当程序开始执行时,系统会在为函数在栈上开辟一块空间以存放函数产生的数据,栈是向下生长的,每当我们开辟一块栈空间,就有一个指针向下移动。

我们编写程序的时候会用到很多的库函数如iostream,vector,string的函数,在整个程序里面这些都只需要一份而且基本上每个程序或者进程需要的都是同一份,在程序执行或者说进程启动时这一份数据就会存放在内存映射段中,映射段内的数据被整个程序所有的线程所共享。

堆区用于我们动态开辟内存使用的,这里的空间是被我们自己开辟,管理和释放的,若是我们使用完后没有主动去释放这块内存就会导致内存泄漏影响程序的效率。

数据段也叫静态区,这是存放全局数据和静态数据的地方(被static修饰的变量)

代码段也叫常量区,可执行的代码存放位置,也是常量的存放地方(如const修饰的变量,平时直接使用的常量"123456789abcd"这些不会改变的都是放在这个地方),这些只是规定的不会改变,其实只要我们能拿到这个位置的地址,通过地址去访问内存的全部数据都是可以修改的。

在操作系统为程序或者说进程分配内存的时候这个表肯定是会复杂很多,并且有相应的算法对应内存的开辟和使用管理,不过在语言层,它也就只需要考虑上图的分配数据管理方式即可。最上层的内核空间就是映射的操作系统的内存地址的空间每个程序都拥有一份是方便程序(进程)与系统的切换,例如需要调用系统接口的时候。

C语言中管理内存的方式

C语言中4个函数用于动态管理内存:malloc/calloc/realloc/free  这四个函数前两个是动态开辟内存的函数

这里我们分别使用malloc和calloc在堆上创建了一块相同大小的空间,malloc的参数是字节数这里一共8字节,calloc的第一个参数代表我们需要创建的空间要存放几个数据,第二个参数代表每一个数据的大小。这两个都是在堆上动态开辟空间的,差异点就是参数和初始化,calloc是会 将开辟的空间内数据都初始化为0,malloc是不理会的,原来里面的数据是怎么样现在还是怎么样。这两个函数的返回值都是一个void*的指针指向开辟好的内存的首地址,因为这里只负责开辟一块规定大小的内存,至于里面存什么数据怎么使用这块内存函数是不管的,所以我们需要对其进行强转为我们需要的类型再进行使用。

realloc函数是用于动态调整开辟后的内存的

这里我是使用realloc将p所指向的空间从原来的8字节改为12字节,若是p所指向的空间后面是有4个字节大小的话就会直接将空间不动向后阔4个字节,若是后面不存在这么大空间的话就会在堆上的其他地方开辟一个连续的12字节的空间再将原来空间的内容拷贝过去。

用以上三个函数开辟空间或者动态调整空间大小都是有机会失败的,若是失败会返回一个NULL空指针,所以正常使用的话是需要对指针进行判断的。

在堆中开辟了空间后这快空间就完全由我们自己管理的,这里我们开辟的内存在后续没有使用需求的时候是需要我们自己去释放这块空间将这块空间交还给操作系统管理的这就是free函数的作用

将指针传递给函数free就会帮我们将空间交换给系统。

C++中的内存管理

C++是兼容C语言的,上述函数在C++中都可以使用,但是大部分时候使用C语言的内存管理函数会有些麻烦,它就只是单纯的给我开辟一段空间,而且失败了也没有任何提示需要我们自己去判断,所以C++也对其进行了改良,做出了new和delete运算符

这是new和delete的基础用法,我们在new后面加个小括号里面是需要存放的数据类型,它会帮我们申请一个int类型数据大小的空间就是4字节,第二个是new后面加个类型再用方括号扩起我们需要的数据个数就会给我们申请4个int类型的空间大小即16个字节,而且不需要我们去强转返回指针类型,可以直接接收。并会再申请失败时报异常。可以再后面进行异常的捕捉。但是new出来的空间是没有对应的函数进行内存的扩充的,当我们需要内存扩充的时候需要手动new一个新空间再将旧空间的值拷贝新空间在delete掉旧空间。

delete就是释放空间这里需要对应单个的对应单个的delete,多个数据的调用delete[]。

自定义类型:

C++中有了自定义类型类,类的初始化需要调用构造函数释放需要调用析构函数,但是C语言中的内存管理函数只会帮我们申请空间和交还空间,所以c++的new和delete更多其实就是为了自定义类型而创造出来的,new和delete根据自定义类型申请空间的时候会调用其对应的构造函数,释放时会调用其析构函数。

operator new 和operator delete

new和delete是用户进行动态内存管理的操作符,operator new 和operator delete是系统提供的全局函数,new和delete操作符就是通过调用operator new 和operator delete来完成内存的动态管理。

 /*
 operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,
尝试执行空               
间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/

 void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
 {
 // try to allocate size bytes
 void *p;
 while ((p = malloc(size)) == 0)
 if (_callnewh(size) == 0)
 {
 // report no memory
 // 如果申请内存失败了,这里会抛出bad_alloc 类型异常
static const std::bad_alloc nomem;
 _RAISE(nomem);
 }
 return (p);
 }




 /*
 operator delete: 该函数最终是通过free来释放空间的
*/

 void operator delete(void *pUserData)
 {
 _CrtMemBlockHeader * pHead;
 RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
if (pUserData == NULL)
 return;
 _mlock(_HEAP_LOCK);  /* block other threads */
 __TRY

 /* get a pointer to memory block header */

 pHead = pHdr(pUserData);

 /* verify block type */

 _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
 _free_dbg( pUserData, pHead->nBlockUse );
 __FINALLY
 _munlock(_HEAP_LOCK);  /* release other threads */
 __END_TRY_FINALLY
 return;
 }




 /*
 free的实现
*/

 #define   
free(p)               
_free_dbg(p, _NORMAL_BLOCK

如上代码,调用的operator new 和operator delete函数实际上也是通过malloc申请内存空间,和free释放内存空间的。

定位new表达式

定位new表达式用于对一块原始是内存空间进行显示调用自定义类型的构造函数来初始化

紧接着new的括号里面是指向动态开辟的内存空间的指针,紧跟着A类的括号里面是类的初始化列表,若是由无参构造函数可以省略。

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

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

相关文章

文心快码帮你解大厂面试题:TCP关闭连接的过程,为什么要4次挥手,为什么最大等待时间是2*MSL?

🔍【大厂面试真题】系列,带你攻克大厂面试真题,秒变offer收割机! ❓今日问题:在8g内存的机器,能否启动一个7G堆大小的java进程? ❤️一起看看文心快码Baidu Comate给出的答案吧!如…

Oracle RAC 修改系统时区避坑指南(深挖篇)

大家好,这里是 Lucifer三思而后行,专注于提升数据库运维效率。 目录 前言环境安装问题重现时区检查修改时区问题分析问题解决 深究根源问题一问题二问题三 写在最后往期精彩文章推荐 前言 昨天遇到一个问题,Oracle RAC 安装完之后&#xff0…

bitsandbytes使用错误:CUDA Setup failed despite GPU being available

参考:https://huggingface.co/docs/bitsandbytes/main/en/installation 报错信息 ======================

【JavaEE精炼宝库】网络原理基础——网络层 | IP协议

文章目录 一、IP 协议的格式二、IP 地址的数量限制三、私有 IP 地址和公网 IP 地址3.1 私有 IP 地址和公网 IP 地址的基本知识:3.2 内网 IP 设备访问外网 IP 设备的过程(NAT 机制): 四、地址管理4.1 网段划分:4.1.1 网…

npm、cnpm、pnpm、yarn包管理工具别傻傻分不清楚了

干啥的: nodejs的包管理工具。 用于自动化处理包的安装、更新、配置和管理。它们之间的主要区别在于它们各自的实现方式、性能优化、以及一些特有的功能。 怎么用: 1、npm 1.1、描述 Node Package Manager默认包管理器从 npm 公共仓库中安装、共享…

.net framework 4.8 开发windows系统服务

ps:旧技术了,有一点局限性,但好像网上记录并不多,或是很零散,比较坑人。故自己记录一下。 项目环境: win 10、.Net framework 4.8,Visual Studio 2019,oracle 12G,ORM是SqlSugar5.…

uniapp video标签无法播放视频

当video标签路径含有中文以及特殊字符视频就会无法播放 解决方法使用encodeURIComponent对路径进行加密处理 videoSrc data.coursewareFile? ${appConfig.apiUrl encodeURIComponent(data.coursewareFile)}: "";最后效果

GHA高质量seo文章怎么写?

撰写高质量SEO文章不仅仅是文字的堆砌,更是对内容的精心打磨,而GHA文章更是如此,想写出一篇GHA文章,首先就要保证以下几点,一定要原创,谷歌对于原创内容是极其看重的,哪怕是伪原创,在…

一种导出PPT到MP4的方法

需求 导出PPT到MP4,并记录每页,每个动作的时间线。通过 MP4时间线 就可以在页面上很方便的放映PPT的内容,并支持翻页点击。 代码 保存每一页的图像信息,用做播放器的缩略图 public void SaveThumbnail(string ppt_filepath, st…

【STL】红黑树的全面探索与红黑树的实现

ps:文章最后有完整的代码 1.红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路…

如何使用IDEA搭建Mybatis框架环境

文章目录 ☕前言为什么学习框架技术Mybatis框架简介 🍹一、如何配置Mybatis框架环境1.1下载需要MyBatis的jar文件1.2部署jar文件1.3创建MyBatis核心配置文件configuration.xml1.4.创建持久类(POJO)和SQL映射文件1.5.创建测试类 🧋二、 MyBatis框架的优缺…

前端性能优化:使用Vue3+TS+Canvas对图片进行压缩后再上传,优化带宽,减小服务器存储成本,减少流量损耗

在上传图片之前,对图片进行压缩。看到这里是不是有点懵,前端怎么压缩图片呢,这不应该是后端做的吗? 但是我在开发的时候接到了这样一个需求,要求对用户上传的图片进行一定的压缩,而且并且尽量还原图片的清…

大模型如何改变世界?李彦宏:未来至少一半人要学会“提问题“

2023年爆火的大模型,对我们来说意味着什么? 百度创始人、董事长兼CEO李彦宏认为,“大模型即将改变世界。” 5月26日,李彦宏参加了在北京举办的2023中关村论坛,发表了题为《大模型改变世界》的演讲。李彦宏认为&#…

2024年新算法-基于SBOA-BP混合神经网络的数据预测(Python代码实现)

在今天的数字化时代,机器学习和人工智能领域的不断发展为数据处理和预测提供了强大的工具。其中,BP神经网络(反向传播神经网络)作为一种经典的网络模型,因其能够处理复杂的非线性问题而备受关注。然而,传统…

吴恩达机器学习课后作业-07kmeans and pca

k-均值与PCA k-均值图片颜色聚类 PCA(主成分分析)对x去均值化图像降维 k-均值 K-均值是最普及的聚类算法,算法接受一个未标记的数据集,然后将数据聚类成不同的组。 K-均值是一个迭代算法,假设我们想要将数据聚类成n个…

python-变量声明、数据类型、标识符

一.变量 1.什么是变量 为什么需要变量呢? 一个程序就是一个世界,不论使用哪种高级程序语言编写代码,变量都是其程序的基本组成单位。如下图所示的sum和sub都是变量。 变量的定义: 变量相当于内存中一个数据存储空间的表示&#…

Spring MVC常用注解及用法

目录 1.建立连接--RequestMapping 2.请求 2.1 传递单个参数 2.2 传递多个参数 2.3 传递对象 2.4 参数重命名--RequestParam 2.5 传递数组 2.6 传递集合 2.7 传递json数据--RequestBody 2.8 获取URL中参数--PathVariable 2.9 上传文件--RequestPart 2.10 获取Cookie--…

bomb 实验

GDB常用命令: GDB调试常用命令-CSDN博客 原理: 编译与反汇编过程-CSDN博客 Bomb实验实现 阶段一: 分析 分配空间:sub $0x8,%rsp 为局部变量分配栈空间。设置参数:mov $0x402400,%esi 将字符串地址加载到 %esi。…

MMsegmentation与MMdeploy简单使用

最近涉及到了图像分割的任务,于是拿来写下博客加深下使用。 MMsegmentation与MMdeploy的环境配置暂不做讲解,在官网和其他博客中有很多说明。 MMdeploy主要是把pt转为 onnx_int8的情况。 MMsegmentation环境配置可以参考 : 安装与配置MMSegmentation 目录…

【管理型文档】软件需求管理过程(原件)

软件需求管理规程应明确需求收集、分析、确认、变更控制及验证等流程,确保需求准确反映用户期望,支撑软件开发。该规程要求系统记录需求来源,通过评审确保需求完整、清晰、无歧义,实施变更控制以维护需求基线稳定,并持…