内存管理方式
内存管理
- 一、C/C++内存分布
- 1、内存空间的介绍
- 2、示例题目
- 3、示例题目图解
- 二、C语言动态内存管理方式
- 1、代码
- 2、介绍
- 三、C++内存管理方式
- 1、概念
- 2、代码
- 3、代码所代表的意义
- 四、new和delete操作自定义类型
- 1、代码
- 2、运行结果
- 3、特点
- 五、operator new与operator delete函数
- 1、概念
- 2、代码
- 3、讲解
- 六、new和delete的实现原理
- 1、内置类型
- 2、自定义类型
- (1)new
- (2)delete
- (3)new T[N]
- (4)delete[]
- 七、定位new表达式(placement-new)
- 1、作用
- 2、使用格式
- 3、使用场景
- 4、代码
- 八、malloc/free和new/delete的区别
- 1、相同点
- 2、不同点
- 九、内存泄漏
- 1、概念
- 2、危害
- 3、内存泄漏的分类
- (1)堆内存泄漏(Heap leak)
- (2)系统资源泄漏
一、C/C++内存分布
1、内存空间的介绍
- 栈/堆栈:存储非静态的局部变量、函数参数、返回值等等,栈是向下增长的。
- 内存映射段:高效的I/O映射方式,用于装载一个共享的动态内存库。用户可以使用系统接口创建共享内存,做进程间通信。
- 堆:用于程序运行时进行动态内存分配,堆是向上增长的。
- 数据段:存储全局数据和静态数据。
- 代码段:存储可执行的代码、只读常量。
2、示例题目
3、示例题目图解
二、C语言动态内存管理方式
1、代码
int main()
{int* p1 = (int*)malloc(sizeof(int));free(p1);int* p2 = (int*)calloc(4, sizeof(int));int* p3 = (int*)realloc(p2, sizeof(int) * 10);free(p3);return 0;
}
2、介绍
三、C++内存管理方式
1、概念
因为C++兼容C语言,所以C语言的内存管理方式在C++中可以继续使用,但在C++中的一些地方使用C语言的那套方式无法达成使用的目的,而且用起来比较麻烦,因此C++提出了自己的内存管理方式,即通过new和delete操作符进行动态内存管理。
2、代码
void Test1()
{int* p4 = new int;int* p5 = new int(5);int* p6 = new int[6] {1, 2, 3, 4, 5, 6};delete p4;delete p5;delete[] p6;
}
3、代码所代表的意义
申请和释放单个元素空间时,使用new和delete操作符;申请和释放连续的空间时,使用new[]和delete[]。注意,new和delete要匹配使用,即使用new开辟的要使用delete去释放,使用new[]开辟的要使用delete[]去释放,否则可能会出问题。
四、new和delete操作自定义类型
1、代码
class A
{
public:A(int a = 10):_a(a){cout << "A(int a = 10)" << this << endl;}~A(){cout << "~A()" << this << endl;}
private:int _a;
};int main()
{A* p1 = (A*)malloc(sizeof(A));A* p2 = new A(20);free(p1);delete p2;A* p3 = (A*)malloc(sizeof(A) * 10);A* p4 = new A[10]{ 20,30,40 };free(p3);delete[] p4;return 0;
}
2、运行结果
3、特点
- 对于自定义类型来说,在申请自定义类型的空间时,new会调用它的构造函数对对象进行初始化,而malloc不会;在释放自定义类型的空间时,delete会调用它的析构函数对对象中的资源进行清理,而free不会。
- 对于内置类型来说,new/delete跟malloc/free没有本质的区别,只有用法的区别,即使用new/delete的用法比较简单。
- 总的来说,new/delete 是为自定义类型准备的。
- new开辟空间失败,不需要检查返回值,因为它开辟空间失败是抛异常;malloc开辟空间失败,需要检查返回值,因为它开辟空间失败是返回空指针。
五、operator new与operator delete函数
1、概念
通过前面的介绍,我们知道new和delete是用户进行动态内存申请和释放的操作符。而operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层调用operator delete全局函数来释放空间。
2、代码
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);
}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)
3、讲解
- operator new函数实际是通过malloc来申请空间的,当malloc申请空间成功时直接返回指向申请出来的空间的指针;当申请空间失败时,尝试执行空间不足的应对措施,如果用户设置了该应对措施,则继续申请空间,否则就抛异常。
- operator delete函数最终是通过free来进行释放空间的操作,如上方的代码中,operator delete函数中有_free_dbg语句,而该语句在free中被重命名为free( p )。
六、new和delete的实现原理
1、内置类型
当申请的空间是内置类型的空间时,new和malloc,delete和free基本类似,不同的地方是:new和delete申请和释放的是单个元素的空间,new[]和delete[]申请和释放的是连续空间,并且new在申请空间失败时会抛异常,malloc会返回NULL。
2、自定义类型
(1)new
- 调用operator new函数申请空间。
- 在申请的空间上调用该自定义类型的构造函数执行初始化操作,完成对对象的构造。
(2)delete
- 在空间上调用该自定义类型的析构函数,完成对对象中资源的清理工作。
- 调用operator delete函数释放对象的空间。
(3)new T[N]
- 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请。
- 在申请的空间上调用N次该自定义类型的构造函数执行对N个对象的初始化操作。
(4)delete[]
- 在欲释放的对象空间上调用N次该自定义类型的析构函数,完成对N个对象中的资源清理工作。
- 调用operator delete[]释放空间,在operator delete[]中实际是调用operator delete去释放空间。
七、定位new表达式(placement-new)
1、作用
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
2、使用格式
- new (place_address) type或者new (place_address) type(initializer-list)。
- place_address必须是一个指针,initializer-list是类型的初始化列表。
3、使用场景
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出来的内存空间没有进行初始化的操作,所以如果是自定义类型的对象,需要使用定位new表达式显式调用该自定义类型的构造函数进行初始化。
4、代码
//自定义的类
class A
{
public:A(int a = 10):_a(a){cout << "A(int a = 10)" << this << endl;}~A(){cout << "~A()" << this << endl;}
private:int _a;
};int main()
{A* p1 = (A*)malloc(sizeof(A));new(p1)A;p1->~A();free(p1);A* p2 = (A*)operator new (sizeof(A));new(p2)A(20);p2->~A();operator delete(p2);return 0;
}
八、malloc/free和new/delete的区别
1、相同点
都是从堆上申请空间,并且需要用户对这些申请出来的空间手动进行释放。
2、不同点
- malloc和free是函数,new和delete是操作符。
- 当申请的是自定义类型的空间时,malloc不会对它进行初始化;而new可以调用它的构造函数对它进行初始化。
- malloc申请空间时,需要手动计算欲申请空间的大小并作为实参进行传递;而new只需在其后跟上空间的类型即可,如果是多个对象,[]中需指定欲申请的对象数量。
- malloc的返回值为void*, 在使用时必须进行强制类型转换;而new不需要,因为new后面跟着空间的类型,而编译器会自动进行那些操作。
- malloc申请空间失败时,返回的是NULL,因此使用时必须进行判空,判断申请空间是否成功;而new不需要,但是new需要捕获异常,因为它申请空间失败时是抛异常。
- 申请自定义类型对象时,malloc与free只会开辟空间,不会调用该自定义类型的构造函数与析构函数;而new在申请空间后会调用该自定义类型的构造函数完成对对象的初始化,delete在释放空间前会调用该自定义类型的析构函数完成对对象空间中的资源清理工作。
九、内存泄漏
1、概念
内存泄漏是指因为疏忽或错误的原因而造成程序未能释放已经不再使用的内存空间的情况。内存泄漏并不是指内存在物理空间上的消失,而是应用程序分配完某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存空间的浪费。
2、危害
长期运行的程序如果出现内存泄漏,会造成很大的影响,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。
3、内存泄漏的分类
(1)堆内存泄漏(Heap leak)
正常的程序在执行中,依据通过malloc/calloc/realloc/new等从堆中分配一块内存空间,当使用完这块空间后必须通过调用相应的free或者delete对这块空间进行释放。但如果程序设计错误等原因导致这部分内存空间没有被释放,那么以后这部分空间将无法再被使用,就会产生Heap Leak。
(2)系统资源泄漏
程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数去释放掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。
本文到这里就结束了,如有错误或者不清楚的地方欢迎评论或者私信
创作不易,如果觉得博主写得不错,请务必点赞、收藏加关注💕💕💕
相关文章:

内存管理方式
内存管理 一、C/C内存分布1、内存空间的介绍2、示例题目3、示例题目图解 二、C语言动态内存管理方式1、代码2、介绍 三、C内存管理方式1、概念2、代码3、代码所代表的意义 四、new和delete操作自定义类型1、代码2、运行结果3、特点 五、operator new与operator delete函数1、概…...

文心一言接入Promptulate,开发复杂LLM应用程序
简介 最近在尝试将文心一言的LLM能力接入Promptulate,故写了一篇博客记录一下,Promptulate 是 Promptulate AI 旗下的大语言模型自动化与应用开发框架,旨在帮助开发者通过更小的成本构建行业级的大模型应用,其包含了LLM领域应用层…...

TDengine函数大全-聚合函数
以下内容来自 TDengine 官方文档 及 GitHub 内容 。 以下所有示例基于 TDengine 3.1.0.3 TDengine函数大全 1.数学函数 2.字符串函数 3.转换函数 4.时间和日期函数 5.聚合函数 6.选择函数 7.时序数据库特有函数 8.系统函数 聚合函数 TDengine函数大全APERCENTILEAVGCOUNTELAPS…...

DRM全解析 —— ADD_FB(2)
接前一篇文章:DRM全解析 —— ADD_FB(1) 本文参考以下博文: DRM驱动(四)之ADD_FB 特此致谢! 上一回围绕libdrm与DRM在Linux内核中的接口: DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, d…...

windows下docker compose方式挂载数据卷volume遇到的问题
例子一,windows 下docker desk top部署TDengine td-compose.yml version: 3 services:tdengine1:image: tdengine/tdengine:latestcontainer_name: tdengine1hostname: tdengine1ports:- 6030:6030- 6041:6041- 6043-6049:6043-6049- 6043-6049:6043-6049/udpresta…...

TCP三次握手四次挥手总结
目录 一、两种传输模式: 二、数据方向: 三、端口的作用: 四、端口类型: 五、三次握手: 六、四次断开 常见面试题 TCP(Transfer control protocol)传输控制协议 一、两种传输模式&#x…...

【0901作业】QTday3 对话框、发布软件、事件处理机制,使用文件相关操作完成记事本的保存功能、处理键盘事件完成圆形的移动
目录 一、思维导图 二、作业 2.1 使用文件相关操作完成记事本的保存功能 2.2 处理键盘事件完成圆形的移动 一、思维导图 二、作业 2.1 使用文件相关操作完成记事本的保存功能 void Widget::on_saveBtn_clicked() {QString filename QFileDialog::getSaveFileName(this,&…...

mysql数据库运行sql:datetime(0) NULL DEFAULT NULL报错【杭州多测师_王sir】
一、错误信息 CREATE TABLE file (id varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 文件md5,name varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,create_time datetime(0) NULL DEFAULT NULL,update_time date…...

手撕二叉平衡树
今天给大家带来的是平衡树的代码实现,如下: #pragma once #include <iostream> #include <map> #include <set> #include <assert.h> #include <math.h> using namespace std; namespace cc {template<class K, clas…...

超图嵌入论文阅读1:对偶机制非均匀超网络嵌入
超图嵌入论文阅读1:对偶机制非均匀超网络嵌入 原文:Nonuniform Hyper-Network Embedding with Dual Mechanism ——TOIS(一区 CCF-A) 背景 超边:每条边可以连接不确定数量的顶点 我们关注超网络的两个属性࿱…...

Qt xml解析之QXmlStreamReader
文章目录 背景QXmlStreamReader简单介绍使用QXmlStreamReader添加头文件<QXmlStreamReader>toString()toInt()完整代码 背景 项目中遇到需要解析某个方法返回的xml字符串,奈何C/C中没有原生的方法可供调用,只能使用第三方库,搜了一圈资…...

Selenium基础 — CSS选择器定位大全
1、css属性定位 css选择器策略示例说明#id#telA选择id"telA"的所有元素。.class.telA选择 class"telA”的所有元素。[属性名属性值][nametelA]除了id和class属性,其他属性的定位格式[attribute][target]选择带有target 属性所有元素。**选择所有元素…...

vue3中keep-alive的使用及结合transition使用
正确用法 在组件中使用(这里结合了 transition 内置动画组件 ) <template><div class"layout clearfix"><router-view v-slot"{ Component, route }"><transition name"fade-transform" mode"…...

【提示工程】询问GPT返回Json结构数据
theme: orange 众所周知,我们可以通过构建的Prompt获取期望的内容,但是通常都是以自然语言返回的,假如我们想得到结构化的数据,比如Json,XML那么怎么办,这篇文章给你一个思路。 理所当然的想法 要实现询问大…...

CSS水平垂直居中方案
1 前言 水平居中、垂直居中是前端面试百问不厌的问题。其实现方案也是多种多样,常叫人头昏眼花。 水平方向可以认为是内联方向,垂直方向认为是块级方向。 2 内联元素的水平垂直居中 首先,常见内联元素有:a、span、em、b、stro…...

SpringBoot入门篇3 - 整合junit、整合mybatis、基于SpringBoot实现ssm整合
目录 1.整合JUnit Spring整合JUnit SpringBoot整合JUnit 测试类注解:SpringBootTest 作用:设置JUnit加载的SpringBoot启动类 2.整合mybatis ①使用spring initializr初始化项目的时候,添加依赖。 ②设置数据源application.yml spring:d…...

C#,《小白学程序》第七课:列表(List)应用之一“编制高铁车次信息表”
1 文本格式 /// <summary> /// 车站信息类 class /// </summary> public class Station { /// <summary> /// 编号 /// </summary> public int Id { get; set; } 0; /// <summary> /// 车站名 /// </summary>…...

周报/月报 Prompt
前言 用 AI 写好一份周报或月报。 文章目录 前言一、目的二、Prompt 设计原则三、模板 一、目的 简单的日程,扩写成一篇高质量的周报; 二、Prompt 设计原则 角色 目标 背景 要求 三、模板 内容生成模板 你是我的周报助手,根据我的工作…...

c++ 学习 之 构造函数的分类和调用类型 深入学习
正文 构造函数是在C中用于创建和初始化对象的特殊函数。构造函数可以根据不同的特性和参数进行分类,以下是一些常见的构造函数分类和详细讲解它们的调用方式: 默认构造函数: 默认构造函数是一个特殊的构造函数,它没有参数&#x…...

Royal TSX 6 Mac多协议远程软件
Royal TSX是一款功能强大的远程桌面管理软件,适用于Mac操作系统。它允许用户通过一个集成的界面来管理和访问多个远程计算机和服务器。 Royal TSX支持多种远程协议,包括RDP、VNC、SSH、Telnet和FTP等,可以方便地连接到Windows、Linux、Mac和其…...

远程管理通道安全SSH协议主机验证过程
可以使用SSH协议进行远程管理通道安全保护,其中涉及的主要安全功能包括主机验证、数据加密性和数据完整性保护。 这里要注意的是【主机验证】和【身份验证】的区别,主机验证是客户端确认所访问的服务端是目标访问对象,比如从从客户端A(192.16…...

.NET 操作 TDengine .NET ORM
TDengine 是国内比较流的时序库之一,支持群集并且免费,在.NET中资料比较少,这篇文章主要介绍SqlSugar ORM来操作TDengine 优点: 1、SqlSugar支持ADO.NET操作来实现TDengine,并且支持了常用的时间函数、支持联表、分…...

SQL Server对象类型(3)——视图(View)
1. 视图概念 与Oracle中的视图类似,SQL Server中的视图也是一种虚的、通过一个查询定义的逻辑对象,主要用于集中、简化、定制用户需求,控住其底层表安全,以及应用系统提供向后兼容等方面。 --注: 1)上述内容中的“虚的”,表示视图本身并不实际包含和存储数据,SQL Ser…...

【LeetCode】剑指 Offer <二刷>(1)
目录 前言: 题目:剑指 Offer 03. 数组中重复的数字 - 力扣(LeetCode) 题目的接口: 解题思路: 代码: 过啦!!! 写在最后: 前言: …...

MySQL事物和存储引擎
事务 一、MySQL事务的概念 事务是一种机制、一个操作序列,包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行。 事务是一个不可分割的工作逻辑单…...

代码随想录算法训练营Day51 | 309. 最佳买卖股票时机含冷冻期 | 714. 买卖股票的最佳时机含手续费 | 股票总结
文章目录 309. 最佳买卖股票时机含冷冻期标准 dp机智的分析解法 714. 买卖股票的最佳时机含手续费贪心算法 股票总结 309. 最佳买卖股票时机含冷冻期 题目链接 | 解题思路 标准 dp 本题多了冷却期的条件,将原本的两个状态变得更复杂了。变化在于,如果…...

C#,《小白学程序》第八课:列表(List)应用之二“编制高铁列车时刻表”
1 文本格式 /// <summary> /// 车站信息类 class /// </summary> public class Station { /// <summary> /// 编号 /// </summary> public int Id { get; set; } 0; /// <summary> /// 车站名 /// </summary&g…...

2、QT的信号与槽
一、什么是信号与槽 一个对象发送一个信号出去,另外一个对象接收到该信号后,会触发相应的槽函数 二、信号与槽的语法 connect(信号的发送者,SIGNAL(信号名称),信号的接收者,SLOT(槽函数)); 1、写法: QT 4 的写法 connect(sende…...

Java代码审计15之Apache log4j2漏洞
文章目录 1、log4j简介2、复现2.1、高版本测试2.2、测试代码2.3、补充之dns探测2.3.1、rmi、ldap也可以dnslog探测 2.3.2、dnslog外带信息 3、漏洞原理3.1、漏洞的危害大的背景3.2、具体的代码调试 4、靶场测试4.1、dns探测4.2、工具下载与使用4.3、测试4.4、手工可以测出&…...

c语言每日一练(13)
前言:每日一练系列,每一期都包含5道选择题,2道编程题,博主会尽可能详细地进行讲解,令初学者也能听的清晰。每日一练系列会持续更新,上学期间将看学业情况更新。 五道选择题: 1、程序运行的结果…...