C/C++内存管理详解

目录

一、C++内存分布

二、C语言与C++内存管理方式

1、C语言中动态内存管理方式:malloc/calloc/realloc/free

2、C++中的内存管理方式:new/delete

三、operator new与operator delete函数

1、函数概念:

2、函数使用:

3、底层原理:

四、new和delete的实现原理

1、对于内置类型:

2、对于自定义类型:​​​​​​​

五、内存泄漏

1、概念:

2、内存泄漏分类:

3、避免内存泄漏:


一、C++内存分布

 c/c++中程序内存区域划分:

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

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

3、堆区:用于程序运行时动态内存分配,堆是可以向上增长的

4、数据段(静态区)--存储全局数据静态数据

5、代码段(常量区):可执行的代码/只读常量

二、C语言与C++内存管理方式

1、C语言中动态内存管理方式:malloc/calloc/realloc/free

malloc:在内存的动态存储区中分配一块长度为size字节的连续区域,参数size为需要内存空间的长度,返回该区域的首地址

calloc:与malloc类似,不同点是函数calloc() 会将所分配的内存空间中的每一位都初始化为零

realloc: 给一个已经分配了地址的指针重新分配空间,可以做到对动态开辟内存大小的调整。

void Test1()
{char* ptr1 = (char*)malloc(sizeof(char));int* ptr2 = (int*)calloc(4, sizeof(int));int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 10);free(ptr1);free(ptr3);
}

2、C++中的内存管理方式:new/delete

C++的内存管理方式:通过newdelete操作符进行动态内存管理

为什么c++要出一套自己的内存管理规则?

1、C语言的申请内存比较繁琐,要强转,要计算大小,要检查返回值

2、无法对自定义类型的空间申请做出很好的控制(针对自定义类型能更好的初始化与清理)

(1)new/delete操作内置类型:

void Test2()
{// 动态申请一个int类型的空间int* ptr1 = new int;// 动态申请一个int类型的空间并初始化为10int* ptr2 = new int(10);// 动态申请10个int类型的空间int* ptr3 = new int[3];// 动态申请10个int类型的空间并初始化/不完全初始化int* ptr4 = new int[10] {1, 2, 3, 4, 5};delete ptr1;delete ptr2;delete[] ptr3;delete[] ptr4;
}

 

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用 new[]和delete[],注意:匹配起来使用

(2)、new和delete操作自定义类型

new和delete相比于malloc和free的优点:

申请空间时:malloc只开空间,new不仅开空间还会调用构造函数初始化

释放空间时:delete会调用析构函数,free不会。

当我们运行以下程序可知:

class A
{
public:A(int a = 0){cout << "A()  // 调用构造函数" << endl;}~A(){cout << "~A()  // 调用析构函数" << endl;}private:int _a;
};int main()
{A* a = new A(1);delete a;return 0;
}

且new在申请内存时不需要像malloc一样检查合法性,new申请空间失败会自动抛异常

void Test3()
{//malloc失败,返回空指针int* ptr1 = (int*)malloc(sizeof(int) * 10);assert(ptr1); //malloc出来的需要检查合法性int* ptr2 = new int; //new出来的不需要检查合法性,失败会自动抛异常
}

三、operator new与operator delete函数

1、函数概念:

注意:operator new和operator delete不是对new和delete的重载,是库函数。

new和delete是用户进行动态内存申请和释放的操作符,operator new 和 operator delete 是系统提供的全局函数new在底层调用operator new全局函数来申请空间,delete在底层通过调用 operator delete全局函数来释放空间。

operator new的本质是对malloc的封装。

  • 该函数实际上就是通过malloc来申请空间,申请成功时直接返回,失败时抛异常

operator delete的本质是对free的封装。

2、函数使用:

void Test4()
{int* ptr2 = (int*)malloc(sizeof(int));free(ptr2);// 使用方法与malloc/free相似int* ptr1 = (int*)operator new(sizeof(int));operator delete(ptr1);
}

 operator new/operator delete与malloc/free的相同点:

  • 功能一样,不会去调用构造函数和析构函数。

不同点:

  • operator new不需要检查开辟空间的合法性,失败就抛异常。

3、底层原理:

new的底层原理:转换成调用operator new + 构造函数

delete的底层原理:转换成调用operator delete + 析构函数

 

operator new与operator delete的类专属重载:

为了避免有些情况下我们反复的向堆申请释放空间,于是产生池化技术(内存池),直接找内存池申请释放空间,此时效率更高更快。new/delete的类专属重载就是在new调用operator new的时候就可以走内存池的机制从而提高效率。

内存池:

内存池是一种内存管理策略,它通过预先分配一定数量的、大小固定的内存块来优化内存分配性能和减少内存碎片化,从而提高资源利用率内存池允许应用程序快速、高效地获取和释放内存,而不需要频繁地从系统内存中分配和释放小块内存。

四、new和delete的实现原理

1、对于内置类型:

对于内置类型,new和malloc,delete和free基本类似,

不同点为:

  • new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间。
  • new在申请空间失败时会抛异常,malloc会返回NULL。

2、对于自定义类型:​​​​​​​

new的原理

  1. 调用operator new函数申请空间。
  2. 在申请的空间上执行构造函数,完成对象的构造。

delete的原理

  1. 在空间上执行析构函数,完成对象中资源的清理工作。
  2. 调用operator delete函数释放对象的空间。

new T[N]的原理

  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对 象空间的申请。
  2. 在申请的空间上执行N次构造函数。

delete[]的原理

  1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理。
  2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间。

 

五、内存泄漏

1、概念:

内存泄漏是一种编程错误,发生在一个程序重复地分配内存未能释放已不再使用的内存。这将导致系统内存逐渐耗尽,最终可能使得程序或整个系统变得不稳定,甚至崩溃。

内存泄漏的危害:

内存泄漏会导致程序持续占用内存而不释放,造成系统性能下降。

当内存泄漏累积到一定程度时,程序运行速度变慢,响应时间变长。

当大量内存被泄漏时,会导致系统内存不足,从而造成使系统崩溃或死锁等问题。

2、内存泄漏分类:

在C/C++程序中一般我们主要关心以下内存泄漏:

堆内存泄漏(Heap leak):

堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一块内存,用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分内存没有被释放,那么以后这部分空间将无法再被使用,就会产生Heap Leak。

系统资源泄漏:

指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。

3、避免内存泄漏:

1、养成良好的编码规范,确保每次分配内存后都有对应的释放内存的操作。

2、使用垃圾回收机制(一种自动管理内存的方式,可以自动回收无用的内存,防止内存泄漏)。

3、采用RAII思想或者智能指针来管理资源。

4、进行内存泄露测试:可以使用一些内存泄露测试工具,比如Valgrind、Memory Profiler等。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【plt.pie绘制饼图】:从入门到精通,只需一篇文章!【Matplotlib可视化】

【&#x1f4ca;plt.pie绘制饼图】&#xff1a;从入门到精通&#xff0c;只需一篇文章&#xff01;【Matplotlib可视化】&#xff01; 利用Matplotlib进行数据可视化示例 &#x1f335;文章目录&#x1f335; &#x1f3a8; 一、饼图初探&#xff1a;基本概念与用途&#x1f4a…

anomalib1.0学习纪实-续1:增加新算法

0、基本信息 现在我要增加一个新算法&#xff1a;DDAD 他的代码&#xff0c;可以在github中找到&#xff1a;GitHub - arimousa/DDAD 一、基础操作&#xff1a; 1、修改anomalib\src\anomalib\models\__init__.py 我增加的第33行和61行&#xff0c; 2、 增加ddad文件夹和文…

趣学贝叶斯统计:概率密度分布(probability density function)

目录 1. 分布:PDF与PMFPDFPMF 2. 将概率密度函数应用于我们的问题用积分量化连续分布积分度量变化率&#xff1a;导数 3. R语言实践4. 小结 1. 分布:PDF与PMF PDF PDF定义在连续值上。在连续型随机变量的情况下&#xff0c;具体取某个数值的概率是0&#xff0c;因此PDF并不直…

idea将springboot打包成jar包

打开idea->view->Tool Windows->Terminal 在控制台输入&#xff1a; mvn clean package

HarmonyOS 通过getInspectorByKey获取指定元素高宽等属性

例如 这里 我们有这样一个组件 Entry Component struct Dom {build() {Column() {Row() {Circle({ width: 200, height: 200 }).fill(#20101010)}.id(ES)}.width(100%).height(100%)} }这里 我们就写了个很基本的组件结构 然后 我们写了个 Circle 组件 定义了宽高 然后 如果我…

设计模式七大原则

七大原则有&#xff1a; 单一原则原则接口隔离原则依赖倒转原则里氏替换原则开闭原则迪米特法则合成复用原则 1 单一职责原则 1.1 基本介绍 ​ 对类来说的&#xff0c;即一个类应该只负责一项职责。 如类A负责两个不同的职责&#xff1a;职责1&#xff0c;职责2。当职责1需…

MATLAB实现朴素贝叶斯分类

朴素贝叶斯&#xff08;Naive Bayes&#xff09;是一种基于贝叶斯定理的分类算法&#xff0c;它假设特征之间相互独立&#xff0c;从而简化了计算复杂性。该算法常用于文本分类、垃圾邮件过滤、情感分析等应用场景。 MATLAB实现鸢尾花数据集分类代码如下&#xff1a; clear lo…

【C语言】通讯录(静态版本+动态版本)思路解析+完整源代码

通讯录 由于代码比较长&#xff0c;为了增加可读性&#xff0c;分成了contact.h&#xff0c;contact.c&#xff0c;test.c&#xff0c;分别用来声明函数或者类型&#xff0c;实现函数功能&#xff0c;测试代码 contact.h 我们希望通讯录具有增加联系人&#xff0c;删除联系人…

Eclipse 创建 Hello World 工程

Eclipse 创建 Hello World 工程 1. Hello WorldReferences Download and install the Eclipse IDE. 1. Hello World Eclipse -> double click -> Launch 单击蓝色方框 (右上角) 最大化 IDE File -> New -> C Project -> Finish Project name&#xff1a;工程名…

【小沐学GIS】基于C++QT绘制三维数字地球Earth(OpenGL)

&#x1f37a;三维数字地球系列相关文章如下&#x1f37a;&#xff1a;1【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第一期2【小沐学GIS】基于C绘制三维数字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第二期3【小沐…

Redis篇----第三篇

系列文章目录 文章目录 系列文章目录前言一、缓存雪崩**二、缓存穿透三、缓存预热四、缓存更新五、缓存降级 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女…

【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题

文章目录 Jprofiler简介1.安装及IDEA集成Jprofiler2.如何监控并解决死锁3.如何监控及解决内存泄露(重点)4.总结5.后话 Jprofiler简介 Jprofilers是针对Java开发的性能分析工具(免费试用10天), 可以对Java程序的内存,CPU,线程,GC,锁等进行监控和分析, 1.安装及IDEA集成Jprofil…

【AIGC】Stable Diffusion的生成参数入门

Stable Diffusion 的生成参数是用来控制图像生成过程的重要设置&#xff0c;下面是一些常见的生成参数及其详解 1、采样器&#xff0c;关于采样器的选择参照作者的上一篇文章 2、采样步数&#xff08;Sampling Steps&#xff09;是指在生成图像时模型执行的总步数&#xff0c…

计算机网络——18无连接传输UDP

无连接传输UDP UDP “尽力而为的”服务&#xff0c;报文段可能 丢失送到应用进程的报文段乱序 无连接 UDP发送端和接收端之间没有握手每个UDP报文段都被独立的处理 UDP被用于 流媒体DNSSNMP 在UDP上实现可靠传输 在应用层增加可靠性应用特定的差错格式 UDP&#xff1a;用户…

unity学习(19)——客户端与服务器合力完成注册功能(1)入门准备

逆向服务器用了三天的时间&#xff0c;但此时觉得一切都值&#xff0c;又可以继续学习了。 服务器中登录请求和注册请求由command变量进行区分&#xff0c;上一层的type变量都是login。 public void process(Session session, SocketModel model) {switch (model.Command){ca…

C++学习:stack

1.stack的定义和结构 stack是一种后进先出(LIF0)的数据结构&#xff0c;使用前需要包含头文件,stack提供了一组函数来操作和访问元素&#xff0c;但它的功能相对较简单。stack的定义和结构如下(仅作了解即可): template<class T, class (ontainer deque<T>> cla…

CTFshow web(php命令执行 68-71)

web68 还是那句话&#xff0c;没看到flag在哪&#xff0c;那就优先找到flag位置 这里cvar_dump(scandir("/")); 直接输出根目录的位置&#xff0c;然后查看源代码&#xff0c;发现flag位置为flag.txt 知道flag在根目录下面的flag.txt直接访问就好了 cinclude(/flag…

element 表单提交图片(表单上传图片)

文章目录 使用场景页面效果前端代码 使用场景 vue2 element 表单提交图片   1.点击【上传图片】按钮择本地图片&#xff08;只能选择一张图片&#xff09;后。   2.点击图片&#xff0c;支持放大查看。   3.点击【保存】按钮&#xff0c;提交表单。 页面效果 前端代码…

K8s服务发现组件之CoreDNS/NodeLocalDNS /kubeDNS

1 coredns 1.1 概述 1.1.1 什么是CoreDNS CoreDNS 是一个灵活可扩展的 DNS 服务器&#xff0c;可以作为 Kubernetes 集群 DNS&#xff0c;在Kubernetes1.12版本之后成为了默认的DNS服务。 与 Kubernetes 一样&#xff0c;CoreDNS 项目由 CNCF 托管。 coredns在K8S中的用途,…

机器人常用传感器分类及一般性要求

机器人传感器的分类 传感技术是先进机器人的三大要素&#xff08;感知、决策和动作&#xff09;之一。根据用途不同&#xff0c;机器人传感器可以分为两大类&#xff1a;用于检测机器人自身状态的内部传感器和用于检测机器人相关环境参数的外部传感器。 内部传感器 内部传感…