当前位置: 首页 > news >正文

【C++】内存管理

目录

  • 一、C/C++内存分布
  • 二、C++内存管理方式
    • 2.1、new/delete操作内置类型
    • 2.2、new和delete操作自定义类型
  • 三、operator new与operator delete函数
    • 3.1、operator new与operator delete函数
  • 四、new和delete的实现原理
    • 4.1、内置类型
    • 4.2、自定义类型
  • 五、定位new表达式(placement-new)
  • 六、常见面试题
    • 6.1、malloc/free和new/delete的区别
    • 6.2、内存泄漏


一、C/C++内存分布

我们先来看看下面一段代码和相关问题

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{static int staticVar = 1;int localVar = 1;int num1[10] = { 1, 2, 3, 4 };char char2[] = "abcd";const char* pChar3 = "abcd";int* ptr1 = (int*)malloc(sizeof(int) * 4);int* ptr2 = (int*)calloc(4, sizeof(int));int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);free(ptr1);free(ptr3);
}
  1. 选择题:
    选项 : A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)
    globalVar在哪里?C    staticGlobalVar在哪里?C
    staticVar在哪里?C     localVar在哪里?A
    num1 在哪里?A
    char2在哪里?A       * char2在哪里?A
    pChar3在哪里?A     * pChar3在哪里?D
    ptr1在哪里?A         * ptr1在哪里?B

  2. 填空题:
    sizeof(num1) = 40;    sizeof(char2) = 5;   strlen(char2) = 4;
    sizeof(pChar3) = 4/8;   strlen(pChar3) = 4;
    sizeof(ptr1) = 4/8;

在这里插入图片描述
说明:

  1. 栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的。
  2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。
  3. 堆用于程序运行时动态内存分配,堆是可以上增长的。
  4. 数据段–存储全局数据和静态数据。
  5. 代码段–可执行的代码/只读常量。

二、C++内存管理方式

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力, 而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

2.1、new/delete操作内置类型

void Test()
{// 动态申请一个int类型的空间int* ptr4 = new int;// 动态申请一个int类型的空间并初始化为10int* ptr5 = new int(10);// 动态申请10个int类型的空间int* ptr6 = new int[3];delete ptr4;delete ptr5;delete[] ptr6;
}

在这里插入图片描述
注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[ ]和delete[ ], 注意:匹配起来使用。

2.2、new和delete操作自定义类型

class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;	}~A(){cout << "~A():" << this << endl;}
private:int _a;
};
int main()
{// new/delete 和 malloc/free最大区别是: // new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数A* p1 = (A*)malloc(sizeof(A));A* p2 = new A(1);free(p1);delete p2;// 内置类型是几乎是一样的int* p3 = (int*)malloc(sizeof(int)); // Cint* p4 = new int;free(p3);delete p4;A* p5 = (A*)malloc(sizeof(A) * 10);A* p6 = new A[10];free(p5);delete[] p6;return 0;
}

注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。


三、operator new与operator delete函数

3.1、operator new与operator delete函数

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

/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;
申请空间失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/
void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{// try to allocate size bytesvoid* 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_FINALLYreturn;
}//free的实现
#define free(p) _free_dbg(p, _NORMAL_BLOCK)

通过上述两个全局函数的实现知道,operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的。


四、new和delete的实现原理

4.1、内置类型

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是: new/delete申请和释放的是单个元素的空间,new[ ]和delete[ ]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL

4.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来释放空间


五、定位new表达式(placement-new)

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。

使用格式:

  • new (place_address) type或者new (place_address) type(initializer-list)
  • place_address必须是一个指针,initializer-list是类型的初始化列表

使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};
// 定位new/replacement new
int main()
{// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行A* p1 = (A*)malloc(sizeof(A));new(p1)A;  // 注意:如果A类的构造函数有参数时,此处需要传参p1->~A();free(p1);A* p2 = (A*)operator new(sizeof(A));new(p2)A(10);p2->~A();operator delete(p2);return 0;
}

六、常见面试题

6.1、malloc/free和new/delete的区别

malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。
不同点

  1. malloc和free是函数,new和delete是操作符
  2. malloc申请的空间不会初始化,new可以初始化
  3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可, 如果是多个对象,[]中指定对象个数即可
  4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
  5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

6.2、内存泄漏

什么是内存泄漏,内存泄漏的危害?

什么是内存泄漏: 内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

内存泄漏的危害: 长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。

相关文章:

【C++】内存管理

目录一、C/C内存分布二、C内存管理方式2.1、new/delete操作内置类型2.2、new和delete操作自定义类型三、operator new与operator delete函数3.1、operator new与operator delete函数四、new和delete的实现原理4.1、内置类型4.2、自定义类型五、定位new表达式(placement-new)六、…...

Dilworth定理

偏序关系 设RRR是集合AAA的一个二元关系&#xff0c;若RRR满足&#xff1a; 1.自反性:∀x∈A\forall x \in A∀x∈A&#xff0c;有xRxxRxxRx 2.反对称性&#xff1a;∀x,y∈A\forall x,y \in A∀x,y∈A&#xff0c;若xRy,yRxxRy,yRxxRy,yRx&#xff0c;则xyxyxy 3.传递性&…...

使用loading动画让你的条件渲染页面更高级

前言在我们做项目的使用常常会使用条件渲染去有选择的给用户展示相关页面&#xff0c;如果渲染的数据或场景比较多比较复杂&#xff0c;那么往往需要3、4s的时间去完成&#xff0c;用户点击了之后就会陷入3、4s的空白期&#xff0c;并且这段时间屏幕是处于一种”未响应“的状态…...

Renegade:基于MPC+Bulletproofs构建的anonymous DEX

1. 引言 白皮书见&#xff1a; Renegade Whitepaper: Protocol Specification, v0.6 开源代码见&#xff1a; https://github.com/renegade-fi/renegade&#xff08;Renegade p2p网络每个节点的核心网络和密码逻辑&#xff09;https://github.com/renegade-fi/mpc-bulletpr…...

二、Plugin The chain/event/query function

The chain function 链函数是所有数据处理都在其中进行的函数。在简单过滤器的情况下&#xff08;本节示例的情况&#xff09;&#xff0c;_chain()函数大多是线性函数——因此对于每个传入的缓冲区&#xff0c;也将输出一个缓冲区。下面是一个非常简单的chain函数的实现: sta…...

了解 PostgreSQL 的扩展查询协议

1.介绍 本篇博客用于解释扩展协议的工作原理以及它与简单查询的区别。 2.简单查询 在PostgreSQL中&#xff0c;客户端连接能够发起两种类型的查询&#xff1a;简单查询和扩展协议查询。 简单查询顾名思义。 当启动 psql 客户端连接到pg服务器时&#xff0c;几乎所有发送的…...

接入网关和隔离网关

文章目录1. 什么是网关&#xff1f;2. 网关的作用是什么&#xff1f;3. 接入网关和隔离网关1. 什么是网关&#xff1f; 网关&#xff08;Gateway&#xff09;是一种网络设备&#xff0c;通常用于将不同网络之间的流量进行转发和路由&#xff0c;将一个网络连接到另一个网络&…...

实用指南:如何在Anolis OS上轻松使用 Kata 安全容器?

文/云原生SIG本篇文章我们将详细介绍怎么轻松在 Anolis OS 上使用 Kata Containers 安全容器&#xff0c;我们将介绍 Kata Container 社区于 2022 年 10 月 10 日最新发行的 Kata3.0.0 的安装部署方式&#xff0c;3.0.0 版本包含了基于袋鼠 RunD 开源的最新 Rust Kata runtime …...

如何锁定Word文档部分文字不被修改

我们知道&#xff0c;想要保护Word文档的内容无法随意更改&#xff0c;可以设置“限制编辑”的保护模式。 那如果实际工作中&#xff0c;只需要固定的一部分内容不能编辑&#xff0c;可以实现吗&#xff1f;答案是肯定的&#xff0c;今天就来说说如何设置Word文档部分文字可修…...

聊聊8万8的私董会,很扎心

聊聊8万8的私董会&#xff0c;很扎心 道几句真心话&#xff0c;很扎心&#xff0c;但也很现实。 如果你喜欢刷抖音&#xff0c;这种感觉应该会更加明显。 股市哀鸿遍野&#xff0c;实体一地鸡毛&#xff0c;我们办公室楼下的门面换了一波又一波。 别说那些不起眼的小生意&a…...

卷积网络与全连接网络的区别

问题卷积神经网络是一类包含卷积计算且具有深度结构的前馈神经网络&#xff0c;是深度学习。卷积神经网络具有表征学习能力&#xff0c;能够按其阶层结构对输入信息进行平移不变分类&#xff0c;因此也被称为“平移不变人工神经网络。全连接神经网络是具有多层感知器的的网络&a…...

【5000左右电脑配置清单】预算不高于5000,不带显示器的电脑配置清单推荐

由于本人是学生党经济有限&#xff0c;预算不高于5000元配一套电脑主机&#xff0c;说实话5000左右的电脑配置已经很好了&#xff0c;今天站长整理了几款配置给大家参考参考&#xff0c;更多电脑配置还请继续关注西安SEO优化站点&#xff01; 配置1&#xff1a; <CPU> I5…...

在 4G 内存的机器上,申请 8G 内存会怎么样?

在 4GB 物理内存的机器上&#xff0c;申请 8G 内存会怎么样&#xff1f; 这个问题在没有前置条件下&#xff0c;就说出答案就是耍流氓。这个问题要考虑三个前置条件&#xff1a; 操作系统是 32 位的&#xff0c;还是 64 位的&#xff1f;申请完 8G 内存后会不会被使用&#x…...

JavaSE学习day9 集合(基础班结束)

1.ArrayList 集合和数组的优势对比&#xff1a; 长度可变 添加数据的时候不需要考虑索引&#xff0c;默认将数据添加到末尾 不能存基本数据类型。只能通过包装。 1.1ArrayList类概述 什么是集合 提供一种存储空间可变的存储模型&#xff0c;存储的数据容量可以发生改变 Ar…...

Python爬虫进阶 - win和linux下selenium使用代理

目录 Windows selenium配置 下载地址 Chrome Chromedriver 版本对应关系 实践测试 操作元素 浏览器操作 获取元素信息 鼠标操作 实战demo selenium添加代理 Linux selenium配置 检查服务器环境 下载安装第三方库&#xff08;最简单版&#xff09; 实践测试 代码…...

力扣-从不订购的客户

大家好&#xff0c;我是空空star&#xff0c;本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目&#xff1a;183. 从不订购的客户二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果总结前言…...

速来!掘金数据时代2022年度隐私计算评选活动火热报名中!

开放隐私计算 开放隐私计算开放隐私计算OpenMPC是国内第一个且影响力最大的隐私计算开放社区。社区秉承开放共享的精神&#xff0c;专注于隐私计算行业的研究与布道。社区致力于隐私计算技术的传播&#xff0c;愿成为中国 “隐私计算最后一公里的服务区”。183篇原创内容公众号…...

Springboot @Test 给Controller接口 写 单元测试

前言 最近有小伙伴问到怎么给 controller的接口写单元测试。 单元测试是开发必不可少的一个环节。 既然有人问到了&#xff0c;那我觉得可能不止一个人不会&#xff0c;那就按照惯例&#xff0c;出手。 正文 内容&#xff1a; 主要是get 和 post 两种请求方式的接口 的 单元测…...

ISO 6721-1~12 ,塑料-电动机械性能的测定,2022更新

ISO 6721-1 :2019 Plastics - Determination of dynamic mechanical properties - Part 1: General principles ISO 6721-1 :2019 塑料 - 电动机械性能的测定. 第1部分:一般原理 ISO 6721-2 :2019 Plastics — Determination of dynamic mechanical properties — Part 2:…...

vue3.2中使用swiper缩略图轮播教程

介绍 在vue3 中使用 swiper 实现缩略图的轮播图效果,具体如下图所示: 使用 切换到项目终端 ,输入命令 npm install swiper --save , 进行安装在 main.js里,引入 swiper.css并使用,具体代码如下;import {createApp } from vue import App from ./App.vue import router…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...