内存管理方式

news2025/1/20 14:55:54

内存管理

  • 一、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_FINALLY
     return;
}

//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)系统资源泄漏

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

本文到这里就结束了,如有错误或者不清楚的地方欢迎评论或者私信
创作不易,如果觉得博主写得不错,请务必点赞、收藏加关注💕💕💕

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

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

相关文章

【算法系列篇】模拟算法

文章目录 前言1.替换所有问号1.1 题目要求1.2 做题思路1.3 Java代码实现 2. 提莫攻击2.1 题目要求2.2 做题思路2.3 Java代码实现 3. N 字形变换3.1 题目要求3.2 做题思路3.3 Java代码实现 4. 外观数列4.1 题目要求4.2 做题思路4.3 Java代码实现 5. 数青蛙5.1 题目要求5.2 做题思…

CXL.mem S2M Message 释义

&#x1f525;点击查看精选 CXL 系列文章&#x1f525; &#x1f525;点击进入【芯片设计验证】社区&#xff0c;查看更多精彩内容&#x1f525; &#x1f4e2; 声明&#xff1a; &#x1f96d; 作者主页&#xff1a;【MangoPapa的CSDN主页】。⚠️ 本文首发于CSDN&#xff0c…

【操作系统】一文快速入门,很适合JAVA后端看

作者简介&#xff1a; 目录 1.概述 2.CPU管理 3.内存管理 4.IO管理 1.概述 操作系统可以看作一个计算机的管理系统&#xff0c;对计算机的硬件资源提供了一套完整的管理解决方案。计算机的硬件组成有五大模块&#xff1a;运算器、控制器、存储器、输入设备、输出设备。操作…

使用candump+grep查看CAN报文

在Linux系统中观察看CAN报文&#xff0c;我们一般使用candump&#xff0c;但是有时候会发现总线上CAN报文太多&#xff0c;例如开启了好几个PDO&#xff0c;这就导致想看的报文被夹杂到报文的海洋里&#xff0c;然后再去找&#xff0c;非常麻烦。 candump也提供了只观察某个报…

LeetCode 无重复字符的最长子串 打败100%的人

&#x1f600;前言 LeetCode上的“无重复字符的最长子串”问题要求我们找到给定字符串中不包含重复字符的最长子串的长度。这个问题是一个典型的滑动窗口技巧的应用&#xff0c;需要有效地处理字符出现的情况来找到解决方案。 . 在本解决方案中&#xff0c;我们将探讨两种不同的…

EMC VNX2代一键关机方法

由于不正确的EMC VNX存储系统的关机导致客户业务中断&#xff0c;数据丢失的案例数不胜数。不正确的关机顺序&#xff0c;很容易造成内存中的数据丢失&#xff0c;进而导致dirty cache&#xff0c;然后系统的LUN和POOL就无法online&#xff0c;业务中断。本文仅仅对EMC 2代产品…

Vue——vue3+element plus实现多选表格使用ajax发送id数组

代码来源: Vue 3结合element plus&#xff08;问题总结二&#xff09;之 table组件实现多选和清除选中&#xff08;在vue3中获取ref 的Dom&#xff09;_multipletableref.value.togglerowselection()打印出来的是u_子时不睡的博客-CSDN博客 前言 为了实现批量删除功能的功能…

linux编程第一部分总结

C多线程安全原则 对象析构很复杂&#xff0c;我们采用shared_ptr和weak_ptr来做 enable_shared_from_this<>是用来做回调的&#xff0c;因为多线程中可能对象的生命周期比传出去的this指针短&#xff0c;同时为了不延长对象的生命周期&#xff0c;我们把shared_ptr转成we…

单目标应用:基于麻雀搜索算法SSA的微电网优化调度MATLAB

一、微网系统运行优化模型 参考文献&#xff1a; [1]李兴莘,张靖,何宇,等.基于改进粒子群算法的微电网多目标优化调度[J].电力科学与工程, 2021, 37(3):7 二、麻雀搜索算法简介 麻雀搜索算法 (Sparrow Search Algorithm, SSA) 是一种新型的群智能优化算法&#xff0c;于2020…

Scalene:Python CPU+GPU+内存分析器,具有人工智能驱动的优化建议

一、前言 Python 是一种广泛使用的编程语言&#xff0c;通常与其他语言编写的库一起使用。在这种情况下&#xff0c;如何提高性能和内存使用率可能会变得很复杂。但是&#xff0c;现在有一个解决方案&#xff0c;可以轻松地解决这些问题 - 分析器。 分析器旨在找出哪些代码段…

一文吃透KMP算法

前言&#xff1a;今天&#xff0c;我们要来学习的字符串的高效匹配算法&#xff0c;KMP算法&#xff0c;用于在一个文本串中查找一个模式串的出现位置。相比于朴素的字符串匹配算法&#xff0c;KMP算法具有更低的时间复杂度&#xff0c;KMP算法的核心思想是利用已匹配的部分信息…

如何在Spring Boot应用中使用Nacos实现动态更新数据源

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

zabbix概述及简单的在centos7安装Zabbix5.0及添加监控对象

目录 一、概述 1、概念 2、Zabbix构成&#xff1a; 3、Zabbix的专业术语包括&#xff1a; 4、Zabbix的工作流程如下&#xff1a; 5、Zabbix的进程包括&#xff1a; 6、Zabbix的监控框架包括&#xff1a; 7、Zabbix的配置流&#xff1a; 8、zabbix程序结构 9、 zabbix…

基于YOLOV8模型的农作机器和行人目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOV8模型的农作机器和行人目标检测系统可用于日常生活中检测与定位农作机和行人目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标…

CXL.cache H2D/D2H 请求响应对应关系

&#x1f525;点击查看精选 CXL 系列文章&#x1f525; &#x1f525;点击进入【芯片设计验证】社区&#xff0c;查看更多精彩内容&#x1f525; &#x1f4e2; 声明&#xff1a; &#x1f96d; 作者主页&#xff1a;【MangoPapa的CSDN主页】。⚠️ 本文首发于CSDN&#xff0c…

【大数据】Apache Iceberg 概述和源代码的构建

Apache Iceberg 概述和源代码的构建 1.数据湖的解决方案 - Iceberg1.1 Iceberg 是什么1.2 Iceberg 的 Table Format 介绍1.3 Iceberg 的核心思想1.4 Iceberg 的元数据管理1.5 Iceberg 的重要特性1.5.1 丰富的计算引擎1.5.2 灵活的文件组织形式1.5.3 优化数据入湖流程1.5.4 增量…

手写RPC框架--3.搭建服务注册与发现目录结构

RPC框架-Gitee代码(麻烦点个Starred, 支持一下吧) RPC框架-GitHub代码(麻烦点个Starred, 支持一下吧) 搭建服务注册与发现目录结构 搭建服务注册与发现目录结构a.基于ZooKeeper的服务发现b.搭建基础工程c.基础代码d.编写架子工程e.创建zookeeper基础目录结构 搭建服务注册与发现…

ISP——3A算法

目录 前沿一. 自动曝光AE1.1. 自动曝光1.2. 18%灰1.3. 测光区域1.4. 摄影曝光加法系统1.5. AE算法1.5.1. 考虑事项1.5.2. AE实现过程 1.6. AE算法 二. 自动对焦AF2.1. 什么是自动对焦2.2. 图像清晰度评价方法2.2.1. Brenner 梯度函数2.2.2. Tenengrad 梯度函数2.2.3. Laplacian…

设计模式-8--模板方法模式(Template Method Pattern)

一、什么是模板方法模式&#xff08;Template Method Pattern&#xff09; 模板方法模式&#xff08;Template Method Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一个算法的骨架&#xff0c;将一些步骤的实现延迟到子类中。模板方法模式允许在不改变算法的…

多机单目标跟踪Cross-Drone Transformer Network for Robust Single Object Tracking

1. 摘要 无人机已被广泛用于各种应用&#xff0c;如空中摄影和军事安全&#xff0c;因为与固定摄像机相比&#xff0c;无人机具有高机动性和广阔的视野。多架无人机跟踪系统可以通过收集不同视角的互补视频片段来提供丰富的目标信息&#xff0c;特别是当目标在某些视角下被遮挡…