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类型的空间并初始化为10
	int* 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等。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习笔记】12 聚类

无监督学习概述 监督学习 在一个典型的监督学习中&#xff0c;训练集有标签&#x1d466; &#xff0c;我们的目标是找到能够区分正样本和负样本的决策边界&#xff0c;需要据此拟合一个假设函数。无监督学习 与此不同的是&#xff0c;在无监督学习中&#xff0c;我们的数据没…

4 月 9 日至 4 月 10 日,Hack.Summit() 2024 首聚香江

Hack.Summit() 是一系列 Web3 开发者大会。2024 年的活动将于 2024 年 4 月 9 日至 4 月 10 日在香港数码港举行。自十年前首次举办以来&#xff0c;此次会议标志着 Hack.Summit() 首次在亚洲举办&#xff0c;香港被选为首次亚洲主办城市&#xff0c;这对 Hack VC 和该地区都具…

BuildAdmin - 免费开源可商用!基于 ThinkPHP8 和 Vue3 等流行技术栈打造的商业级后台管理系统

一款包含 PHP 服务端和 Vue 前端代码的 admin 管理系统&#xff0c;实用性很强&#xff0c;推荐给大家。 BuildAdmin 是一个成熟的后台管理系统&#xff0c;后端服务采用 ThinkPHP8 &#xff0c;数据库使用 Mysql&#xff0c;前端部分则使用当前流行的 Vue3 / TypeScript / Vi…

Netty Review - ByteBuf扩容机制源码解析

文章目录 Pre概述前置知识&#xff1a; 名词解释writeByte 源码解析实现ensureWritable0(minWritableBytes)ensureWritable0alloc().calculateNewCapacity 总结 Pre Netty Review - 直接内存的应用及源码分析 Netty Review - 底层零拷贝源码解析 Netty Review - ByteBuf内存…

python - OSError:错误没有名为 [‘pytorch_model.bin‘

python - OSError&#xff1a;错误没有名为 [‘pytorch_model.bin’] 自己训练的模型存储好了以后 model MT5ForConditionalGeneration.from_pretrained(“ner/best”) 之前还可以跑 现在报错 错误没有名为 [‘pytorch_model.bin’] 还原了一下conda env 把四版变成三版了 …

人工智能学习与实训笔记(十五):Scikit-learn库的基础与使用

人工智能专栏文章汇总&#xff1a;人工智能学习专栏文章汇总-CSDN博客 本篇目录 一、介绍 1. 1 Scikit-learn的发展历程及定义 1.2 理解算法包、算法库及算法框架之间的区别和联系 二、Scikit-learn官网结构 三、安装与设置 3.1 Python环境的安装与配置 3.2 Scikit-lea…

【精选】Java面向对象进阶——接口细节:成员特点和接口的各种关系

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

1.逆向基础

文章目录 一、前言二、什么是逆向&#xff1f;三、软件逆向四、逆向分析技术五、文本字符六、Windows系统1.Win API2.WOW643.Windows消息机制4.虚拟内存 一、前言 原文以及后续文章可点击查看&#xff1a;逆向基础 逆向真的是一个很宏大的话题&#xff0c;而且大多数都是相当…

从代码的层面掌握LLM的路线

原则&#xff1a;从易到难&#xff0c;只用 pytorch 从第一个项目来熟悉 transformer 的使用&#xff1b; 从第二个项目来掌握对训练数据的使用方法及 transformer 的 decoder 的细节&#xff1b; 从第三个项目来理解 LLM 的整个过程&#xff1b; 1&#xff0c;Transformer t…

2024/2/17 图论 最短路入门 dijkstra 1

目录 算法思路 Dijkstra求最短路 AcWing 849. Dijkstra求最短路 I - AcWing 850. Dijkstra求最短路 II - AcWing题库 最短路 最短路 - HDU 2544 - Virtual Judge (vjudge.net) 【模板】单源最短路径&#xff08;弱化版&#xff09; P3371 【模板】单源最短路径&#xf…

echarts制作两个柱状图

let colorList[#02ce8b,#ffbe62,#f17373]; let data1 [90,80,70,50] option { title:[{ // 第一个标题text: 环保检测, // 主标题textStyle: { // 主标题样式color: #333,fontWeight: bold,fontSize: 16},left: 20%, // 定位到适合的位置top: 10%, // 定位到适合的位置},{ //…

【plt.scatter绘制散点图】:从入门到精通,只需一篇文章!【Matplotlib】

【plt.scatter绘制散点图】&#xff1a;从入门到精通&#xff0c;只需一篇文章&#xff01;【Matplotlib】&#xff01;&#x1f680; 利用Matplotlib进行数据可视化示例 &#x1f335;文章目录&#x1f335; 一、plt.scatter入门&#xff1a;轻松迈出第一步 &#x1f463;二、…

各类电纸书使用体验

对移动阅读一直有着强烈的愿望&#xff0c;想要一个易于携带&#xff0c;又能看着比较大气的电子阅读器&#xff0c;这是一个矛盾...所以现在用着海信Hi Reader Pro&#xff0c;还想再寻找一个合适的家用阅读器&#xff0c;对自己用过的阅读器总结一下&#xff0c;给大家做个参…

图像卷积、步长、填充、特征图、多通道卷积、权重共享、感受野、池化

图像卷积、步长、填充、特征图、多通道卷积、权重共享、感受野、池化 卷积神经网络的一些基本概念&#xff1a;图像卷积、步长、填充、特征图、多通道卷积、权重共享、感受野、池化 1.图像卷积、步长、填充 图像卷积&#xff1a;卷积核矩阵在一个原始图像矩阵上 “从上往下、…

XUbuntu22.04之apt与snap如何重装软件(二百一十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Vue2学习第二天

Vue2 学习第二天 1. 数据绑定 Vue 中有 2 种数据绑定的方式&#xff1a; 单向绑定(v-bind)&#xff1a;数据只能从 data 流向页面。双向绑定(v-model)&#xff1a;数据不仅能从 data 流向页面&#xff0c;还可以从页面流向 data。 备注&#xff1a; 双向绑定一般都应用在表单…

比特币 P2PKH、P2SH

标准脚本P2PKH、P2SH 区块链重要基础知识7-1——标准脚本P2PKH、P2SH-CSDN博客 比特币中P2SH(pay-to-script-hash)多重签名的锁定脚本和解锁脚本 https://www.cnblogs.com/itlgl/p/10419325.html

Python算法题集_将有序数组转换为二叉搜索树

Python算法题集_将有序数组转换为二叉搜索树 题108&#xff1a;将有序数组转换为二叉搜索树1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【极简代码递归】2) 改进版一【多行代码递归】3) 改进版二【极简代码递归传递下标】 4. 最优算法 本文为…

StarRocks表设计——分区分桶与副本数

目录 一、数据分布 1.1 概述 1.2 数据分布方式 1.2.1 Round-Robin 1.2.2 Range 1.2.3 List 1.2.4 Hash 1.3 StarRocks的数据分布方式 1.3.1 不分区 Hash分桶 1.3.2 Range分区Hash分桶 三、分区 3.1 分区概述 3.2 创建分区 3.2.1 手动创建分区 3.2.2 批量创建分区…

Stable Diffusion系列(五):原理剖析——从文字到图片的神奇魔法(扩散篇)

文章目录 DDPM论文整体原理前向扩散过程反向扩散过程模型训练过程模型生成过程概率分布视角参数模型设置论文结果分析 要想完成SD中从文字到图片的操作&#xff0c;必须要做到两步&#xff0c;第一步是理解文字输入包含的语义&#xff0c;第二步是利用语义引导图片的生成。下面…