【C++】内存管理知识

news2025/7/20 12:08:12

💙作者:阿润菜菜

📖专栏:C++


本文目录

C/C++内存区域分布

对比C语言内存管理的方式

C++内存管理的方式

operator new与operator delete函数(new和delete实现的底层调用)

new和delete的实现原理

malloc/free和new/delete的区别


C/C++内存区域分布

我们熟知C&C++中内存区域有:栈 、堆、数据段(静态区)、代码段(常量区) 

 对于内存分布的说明

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

对比C语言内存管理的方式

我们在C语言中是如何进行内存管理的?  一般通过以下四个命令:malloc/calloc/realloc/free

 malloc的实现原理? glibc中malloc实现原理

void Test ()
{
int* p1 = (int*) malloc(sizeof(int));
free(p1);
// 1.malloc/calloc/realloc的区别是什么?
int* p2 = (int*)calloc(4, sizeof (int));
int* p3 = (int*)realloc(p2, sizeof(int)*10);
// 这里需要free(p2)吗?
free(p3 );
}

realloc 异地扩容 不需要free原指针 否则二次释放

问题1:malloc/calloc/realloc的区别?  

相同点:

1.都是从堆上申请空间;
2.都需要对返回值判空;
3.都需要用户free释放;
4.返回值类型相同(都是void*);
5.都需要类型转化;
6.底层实现是一样的,都需要开辟多余的空间,用来维护申请的空间。

不同点:
2.calloc函数,原型void *calloc(size_t n, size_t size);会对申请空间初始化,并且初始化为0(数据量大时效率较malloc要低);
3.malloc函数,原型void *malloc(unsigned int num_bytes);申请空间须使用memset进行初始化;
4.realloc函数,原型void realloc(void *ptr, size_t new_Size);是对已经存在的空间进行调整,当第一个参数传入NULL的时候和malloc函数一样,其扩容后地址和原先地址可能是不一样的,这取决于扩容的内存大小。

  问题2:malloc的实现原理? glibc中malloc实现原理

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

C++内存管理的方式

在C++中我们使用new和delete操作符进行动态内存管理操作。

new 初始化内置类型

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

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

new 和delete 一定要匹配使用,不要和C语言的内存管理方式进行交叉使用,否则会出现程序崩溃的问题(内存泄露)。

在new和malloc系列里 有底层实现机制关联交叉,可能恰巧没问题,可能有问题,所以建议不能匹配使用。

new初始化自定义类型 

在申请自定义类型的空间时, new 会调用构造函数, delete 会调用析构函数,而 malloc free 不会。
#include<iostream>
using namespace std;
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对于【自定义类型】除了开空间,还会调用构造和析构函数
		A* p1 = (A*)malloc(sizeof(A));
	A* p2 = new A(1);
	free(p1);
	delete p2;
	// 内置类型是几乎是一样的
	int* p3 = (int*)malloc(sizeof(int)); // C
	int* 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;
}

结果:

operator newoperator delete函数(new和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 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);
}
/*
free的实现
*/
#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)
/*

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;
}

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

newdelete的实现原理

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

2.如果申请的是自定义类型空间,new会调用全局函数operator new申请空间,并在申请空间上调用构造函数,完成对象的构造;delete会在空间上执行析构函数,完成对象的清理工作,并调用operator delete函数释放对象空间。

3.当申请空间为new T[N]new会调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请,并在申请的空间上执行N次构造函数;delete会在在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理,并调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间。

malloc/freenew/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在释放空间前会调用析构函数完成 空间中资源的清理

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

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

相关文章

行为型设计模式之中介者模式

中介者模式 中介者模式又称为调解者模式或调停者模式&#xff0c;属于行为型模式。它用一个中介对象封装系列的对象交互&#xff0c;中介者使各对象不需要显示地相互作用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互。 中介者模式包装了一系列对…

「TCG 规范解读」第11章 TPM工作组 TCG算法注册表

可信计算组织&#xff08;Ttrusted Computing Group,TCG&#xff09;是一个非盈利的工业标准组织&#xff0c;它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立&#xff0c;并采纳了由可信计算平台联盟&#xff08;the Trusted Computing Platform Alli…

allure简介

allure介绍allure是一个轻量级&#xff0c;灵活的&#xff0c;支持多语言的测试报告工具多平台的&#xff0c;奢华的report框架可以为dev/qa提供详尽的测试报告、测试步骤、log也可以为管理层提供high level统计报告java语言开发的&#xff0c;支持pytest,javaScript,PHP等可以…

springcloud入门+组件使用

代码gitee地址&#xff1a;https://gitee.com/bing520/springcloud 集群 cluster&#xff1a; 同一中软件服务的多个服务节点共同为系统提供服务过程&#xff0c;称之为软件服务集群。 分布式 distribute&#xff1a; 不同软件集群共同为一个系统提供服务&#xff0c;这个系统…

图解LeetCode——剑指 Offer 48. 最长不含重复字符的子字符串

一、题目 请从字符串中找出一个最长的不包含重复字符的子字符串&#xff0c;计算该最长子字符串的长度。 二、示例 2.1> 示例 1: 【输入】 "abcabcbb" 【输出】 3 【解释】 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。 2.2> 示…

深入浅出深度学习Pytroch

本文将以通俗易懂的方式&#xff0c;深入浅出地为您揭开深度学习模型构建与训练的面纱&#xff1a; 深度学习数据data模型model损失函数loss优化optimizer可视化visualizer深度学习 数据data 模型model 损失函数loss 优化optimizer 可视化visualizer深度学习数据data模型m…

IP-GUARD离线的客户端如何更新策略?

在控制台上对指定客户端设置好策略后,在计算机树中找到该客户端右键-“策略导出”,导出相应的ipz格式的文件拿到离线的客户端上,客户端运行PolicyImportTool.exe工具,把ipz策略文件导入即可。

软件测试学习什么?好就业么

软件测试需要学习测试环境、网络环境、windows环境、数据库管理、编程技巧&#xff08;java编程设计&#xff0c;脚本语言&#xff0c;设计工具&#xff0c;XML编程、软件测试技术&#xff0c;测试理论&#xff0c;方法&#xff0c;流程&#xff0c;文档写作&#xff0c;测试工…

Blazor入门100天 : 身份验证和授权 (5) - 本地化资源

目录 建立默认带身份验证 Blazor 程序角色/组件/特性/过程逻辑DB 改 Sqlite将自定义字段添加到用户表脚手架拉取IDS文件,本地化资源freesql 生成实体类,freesql 管理ids数据表初始化 Roles,freesql 外键 > 导航属性完善 freesql 和 bb 特性 本节源码 https://github.com/…

FreeRTOS入门(01):基础说明与使用演示

文章目录目的基础说明系统移植基础使用演示数据类型和命名风格总结碎碎念目的 FreeRTOS是一个现在非常流行的实时操作系统&#xff08;Real Time Operating System&#xff09;。本文将介绍FreeRTOS入门使用相关内容&#xff0c;这篇是第一篇&#xff0c;主要介绍基础背景方面…

追梦之旅【数据结构篇】——详解C语言动态实现带头结点的双向循环链表结构

详解C语言动态实现带头结点的双向循环链表结构~&#x1f60e;前言&#x1f64c;预备小知识&#x1f49e;链表的概念及结构&#x1f64c;预备小知识&#x1f49e;链表的概念及结构&#x1f64c;带头结点的双向循环链表结构&#x1f64c;整体实现内容分析&#x1f49e;1.头文件编…

openpose在win下环境配置

1.下载OpenPose库 以下二选一进行下载源码 (1)git进行下载 打开GitHub Desktop或者Powershell git clone https://github.com/CMU-Perceptual-Computing-Lab/openpose cd openpose/ git submodule update --init --recursive --remote(2)在github上手动下载 由于下载环境问…

SpringCloud Alibaba 之Nacos集群部署-高可用保证

文章目录Nacos集群部署Linux部署docker部署&#xff08;参考待验证&#xff09;Nacos 集群的工作原理Nacos 集群中 Leader 节点是如何产生的Nacos 节点间的数据同步过程官方推荐用户把所有服务列表放到一个vip下面&#xff0c;然后挂到一个域名下面。http://nacos.com:port/ope…

go进阶(1) -深入理解goroutine并发运行机制

并发指的是同时进行多个任务的程序&#xff0c;Web处理请求&#xff0c;读写处理操作&#xff0c;I/O操作都可以充分利用并发增长处理速度&#xff0c;随着网络的普及&#xff0c;并发操作逐渐不可或缺 一、goroutine简述 在Golang中一个goroutines就是一个执行单元&#xff…

活动报名丨亚马逊科学家杨靖锋:复现和使用GPT3/ChatGPT的想法

2023年2月23日&#xff08;星期四&#xff09;11:00-12:00&#xff0c;由智源社区主办的「智源LIVE 第30期丨亚马逊科学家杨靖锋讲解『一些关于复现和使用GPT3/ChatGPT的想法』将在线举办&#xff0c;敬请期待。杨靖锋杨靖锋是来自亚马逊的科学家。他的研究主要集中在自然语言处…

ESP32设备驱动-深度休眠与唤醒

深度休眠与唤醒 文章目录 深度休眠与唤醒1、ESP32的休眠模式介绍1.1 ESP32的休眠模式1.2 RTC_GPIO1.3 唤醒源1.4 唤醒流程2、软件准备3、硬件准备4、定时器唤醒5、触摸唤醒6、外部中断唤醒6.1 外部中断ext0唤醒6.2 外部中断ext1唤醒6.3 多GPIO唤醒本文将详细在Arduino IDE中如何…

Spring MVC常用功能及注解

目录 一、什么是Spring MVC 1.1 Spring MVC定义 1.2 MVC定义 1.3 MVC和Spring MVC的关系 1.4 Spring MVC的作用 二、Spring MVC的使用 2.1 Spring MVC的创建和连接 2.1.1 RequestMapping注解 2.1.2 GetMapping注解 2.1.3 PostMapping注解 2.2 获取参数 2.2.1 获取单…

unbound部署DNS

dns的主要作用是将域名解析为ip地址然后在进行访问 安装配置dns准备3台服务器&#xff08;地址都要设置为静态的以便自己配置dns&#xff09;192.168.92.1 用户ip地址&#xff08;windows&#xff09; 192.168.92.132 dns服务器地址 192.168.92.133 web服务器地址 dns服务器 …

网络编程之TCP 网络应用程序开发流程

TCP 网络应用程序开发流程学习目标能够知道TCP客户端程序的开发流程1. TCP 网络应用程序开发流程的介绍TCP 网络应用程序开发分为:TCP 客户端程序开发TCP 服务端程序开发说明:客户端程序是指运行在用户设备上的程序 服务端程序是指运行在服务器设备上的程序&#xff0c;专门为客…

【沐风老师】3DMAX橱柜生成器工具使用教程

3DMAX橱柜生成器工具使用教程 【生成的橱柜模型】 3DMAX橱柜生成器&#xff08;Kitchen Cabinet Creator&#xff09;用于在3ds Max中自动制作橱柜模型。是需要频繁设计厨房、家具和室内设计的用户的理想工具插件&#xff0c;也是所有希望通过点击几下鼠标来填充一些空白空间的…