C/C++内存管理【C++】

news2024/11/19 20:42:46

目录

  • 一、 C/C++内存分布
    • 1. C++内存管理方式
      • (1) new和delete操作内置类型
      • (2) new和delete操作自定义类型
  • 二、 operator new与operator delete函数
  • 三、 malloc/free和new/delete的区别
  • 四、内存泄漏

一、 C/C++内存分布

在这里插入图片描述
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.代码段(常量区)
    1.globalVar在哪里?____ 2.staticGlobalVar在哪里?____
    3.staticVar在哪里?____ 4.localVar在哪里?____
    5.num1 在哪里?____
    6.char2在哪里?____ 7.*char2在哪里?___
    8.pChar3在哪里?____ 9.*pChar3在哪里?____
    10.ptr1在哪里?____ 11.*ptr1在哪里?____
    选择答案:
    C C C A A A A A D A B
  2. 填空题:
    sizeof(num1) = ____;
    sizeof(char2) = ____; strlen(char2) = ____;
    sizeof(pChar3) = ____; strlen(pChar3) = ____;
    sizeof(ptr1) = ____;
    答案: 40 5 4 4/8 4 4/8

C语言中动态内存管理方式:malloc/calloc/realloc/free等
C语言动态内存详细介绍 请猛戳此处

1. C++内存管理方式

C++提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理

当然C语言内存管理方式在C++中可以继续使用

(1) new和delete操作内置类型

只分配空间

// 例 1 在堆上分配一个空间
	int* p1 = new int; //表示在堆上动态分配一个整数的大小的内存,返回的地址赋值给指针变量 p1
	//...
	delete p1;	//使用 new 分配的内存必须在不再需要时手动释放,以避免内存泄漏
// 例 2 在堆上分配多个空间
	int* p2 = new int[10]; //表示在堆上要多个int对象,p2 是一个指向整数的指针,它被初始化为新分配的数组的首地址
	//...
	delete[] p2;		   //注意释放的形式

分配空间同时初始化

// 例 1 分配一个空间并初始化
	//在堆上动态分配了一个整型变量并初始化为10,指向该整型变量的指针赋值给指针变量p3
	int* p3 = new int(10);
	//...
	delete p3;
// 例 2 分配一个空间并初始化
	int* p4 = new int[10] {1,2,3,4,5};	//在堆上动态分配了多个空间并部分初始化,然后将指向该数组首元素的指针赋值给指针变量p4
	//...
	delete[] p4;

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

(2) new和delete操作自定义类型

// 例如 链表
struct ListNode
{
	~ListNode()
	{
		_next = nullptr;
		_prev = nullptr;
		_val = 0;
		cout << "~ListNode()" << endl;
	}
	ListNode* _next;
	ListNode* _prev;
	int _val;

	//构造
	ListNode(int val)
		:_next(nullptr)
		,_prev(nullptr)
		,_val(val)
	{}
};

int main() 
{
	//new操作符 在为自定义类型申请空间时,会去调用构造函数
	//如果new失败了后抛异常,不需要手动检查
	ListNode* node1 = new ListNode(1);
	ListNode* node2 = new ListNode(2);
	ListNode* node3 = new ListNode(3);

	//delete操作符 会去调用析构函数
	delete node1;
	delete node2;
	delete node3;

	return 0;
}

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

二、 operator new与operator delete函数

new 和 delete 是进行动态内存申请和释放的操作符

operator new 和 operator delete 是 系统提供的全局函数

new 在底层会去调用operator new 全局函数 来 申请空间,delete 在底层通过operator delete全局函数来释放空间

operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试执行空间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。

	// 对于内置类型,本质和malloc并没有什么区别
	int* p1 = (int*)operator new(10*4);	
	//注意 operator new 不是运算符重载
	//int *p1 = (int*)new(10*4);	//error,运算符重载
	//对于自定义类型,
	A* ptr1 = new A;
	A* ptr2 = new A[10];	//动态分配了一个包含10个 A 类型对象的数组

自定义类型 汇编
在这里插入图片描述
调用的底层顺序
在这里插入图片描述
operator new 是对 malloc 的封装,为了 解决失败后进行抛异常 和 实现new

new的原理:调用operator new函数申请空间,再申请的空间上执行构造函数,完成对象的构造

new A[n]的原理 : 调用operator new[]函数,再operator new[]中实际调用operator new函数完成n个对
象空间的申请,再申请的空间上执行n次构造函数

operator delete: 该函数最终是通过free来释放空间的

对于内置类型的delete本质上和free区别不大

对于自定义类型

	//对于自定义类型,
	A* ptr1 = new A;	//operator new + 1次构造
	A* ptr2 = new A[10];	//operator new[] + 10次构造

// 注意 这里是先进行 析构 再去调用 operator delete
	delete ptr1;	// 先 1次析构 再去调用operator delete
	delete[] ptr2;	// 先 10次析构 再去调用 operator delete[]

operator new 和 operator new[] 的区别 : 在汇编底层,如果有需要时,operator new[] 首地址前多开辟空间,用来记录所要进行析构的次数

三、 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需要捕获异常

特性层面上 :

申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数和析构函数;
new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

四、内存泄漏

指程序在申请内存后,无法释放已不再使用的内存空间的现象。简单来说,就是程序在动态分配了一块内存后,丢失了对该内存区域的控制权,导致即使程序不再需要这块内存,操作系统也无法将其回收供其他进程或程序使用。

简单地说:
一块已经不在使用的内存空间,没有释放

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

C++中预防和解决内存泄漏的方法包括:

手动管理:确保每一块动态分配的内存都有对应的释放操作,即对每一个 new 操作都应有一个相应的 delete 操作。

智能指针:使用C++11引入的智能指针,如 std::unique_ptr、std::shared_ptr
等,它们会在适当的时候自动释放所管理的对象,大大减少了手动管理内存带来的问题。

容器管理:使用STL容器如 std::vector、std::map 等,它们内部会自动管理内存。

内存检测工具:利用内存分析工具如Valgrind、AddressSanitizer等进行调试和检测,找出程序中的内存泄漏点。

编程范式:采用RAII(Resource Acquisition Is
Initialization)原则编写代码,确保资源在创建的同时就确定了其生命周期。

良好的编程习惯:避免循环内反复分配内存而不释放,注意在函数返回前释放临时分配的内存等。

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

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

相关文章

红帆ioffice-udfGetDocStep.asmx存在SQL注入漏洞

产品简介 红帆iOffice.net从最早满足医院行政办公需求&#xff08;传统OA&#xff09;&#xff0c;到目前融合了卫生主管部门的管理规范和众多行业特色应用&#xff0c;是目前唯一定位于解决医院综合业务管理的软件&#xff0c;是最符合医院行业特点的医院综合业务管理平台&am…

上门服务小程序|上门服务系统成品功能包含哪些?

随着移动互联网的快速发展&#xff0c;上门服务小程序成为了一种创新的家政服务模式。它不仅为用户带来了极大的便利&#xff0c;还能在提高服务效率和质量方面发挥作用。通过上门服务小程序&#xff0c;用户可以轻松预约按摩或理疗服务&#xff0c;无需繁琐操作&#xff0c;只…

9、JavaWeb-文件上传-配置文件

P146 案例-文件上传-简介 文件上传&#xff0c;将本地图片、视频等文件上传到服务器&#xff0c;供其他用户浏览下载的过程。 文件上传前端页面三要素&#xff1a; 如果前端表单的编码格式选择的默认编码方式x-www.form-urlencoded&#xff0c;则提交的文件仅仅是文件名&…

【Linux进阶之路】网络 —— “?“ (下)

文章目录 前言一、概念铺垫1.TCP2.全双工 二、网络版本计算器1. 原理简要2. 实现框架&&代码2.1 封装socket2.2 客户端与服务端2.3 封装与解包2.4 请求与响应2.5 对数据进行处理2.6 主程序逻辑 3.Json的简单使用 总结尾序 前言 在上文我们学习使用套接字的相关接口进行了…

Python实现广义泊松模型(GeneralizedPoisson算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 广义泊松模型&#xff08;Generalized Poisson Model&#xff09;是一种统计学中用于处理数据的分析方…

MATLAB环境下滚动轴承复合故障仿真信号及时频谱

滚动轴承是一种广泛应用于各类旋转机械的通用基础部件&#xff0c;其运行状态的正常与否往往会对于整台机器的寿命、可靠性和精度等性能产生直接的影响。据统计&#xff0c;旋转机械中30%的故障和大型异步电机中44%的故障是由故障轴承引起的&#xff0c;而位于轴承内圈和外圈的…

浏览器的缓存导致的问题

同一个网站 频繁回退进入&#xff0c;音频播放器失效等问题问题 1.打开浏览器-更多工具-任务管理器 2.可以看到缓存页面进程 3.频繁回退进入 就会出现问题 解决方法&#xff1a; try {var bfWorker new Worker(window.URL.createObjectURL(new Blob([1])));window.addEvent…

智慧城市如何助力疫情防控:科技赋能城市安全

目录 一、引言 二、智慧城市与疫情防控的紧密结合 三、智慧城市在疫情防控中的具体应用 1、智能监测与预警系统 2、智慧医疗与健康管理 3、智能交通与物流管理 4、智慧社区与基层防控 四、科技赋能城市安全的未来展望 五、结论 一、引言 近年来&#xff0c;全球范围内…

Python 匿名函数lambda()详解

一、匿名函数定义 lambda 函数是一个匿名函数&#xff08;即&#xff0c;没有名称定义&#xff09;&#xff0c;它可以接受任意数量的参数&#xff0c;但与普通函数不同&#xff0c;它只计算并返回一个表达式 二、匿名函数语法 lambda arguments&#xff08;参数&#xff09;: …

Qt初识 - 编写Hello World的两种方式 | 对象树

目录 一、通过图形化方式&#xff0c;在界面上创建出一个控件 二、通过代码方式&#xff0c;创建Hello World 三、Qt 内存泄漏问题 (一) 对象树 一、通过图形化方式&#xff0c;在界面上创建出一个控件 创建项目后&#xff0c;打开双击forms文件夹中的ui文件&#xff0c;可…

RFID-科技的“隐秘耳语者”

RFID-科技的“隐秘耳语者” 想象一下&#xff0c;你身处一个光线昏暗的环境中&#xff0c;周围的一切都被厚厚的阴影笼罩。这时&#xff0c;你需要识别并获取一个物体的信息&#xff0c;你会选择怎么做&#xff1f;是点亮灯光&#xff0c;用肉眼仔细观察&#xff0c;还是打开扫…

JetPack入门

先导入依赖 implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") 1.使用LifeCycle解耦页面与组件 Activity package com.tiger.lifecycle;import android.annotation.SuppressLint; import android.os.Bundle; import android.os.SystemClock; impo…

【粉丝福利】探秘内部审计数字化之道:精准解析转型方法与成功路径

&#x1f33c;前言 内部审计是一种独立的、客观的确认和咨询活动&#xff0c;包括鉴证、识别和分析问题以及提供管理建议和解决方案。狭义的数字化转型是指将企业经营管理和业务操作的各种行为、状态和结果用数字的形式来记录和存储&#xff0c;据此再对数据进行挖掘、分析和应…

力资源视角的数字化应用

人力资源视角的数字化应用 随着科技的不断发展&#xff0c;数字化应用已经渗透到我们生活的方方面面&#xff0c;而人力资源管理也不例外。从招聘到员工培训&#xff0c;从绩效管理到薪酬福利&#xff0c;数字化应用正在彻底改变人力资源的工作方式和流程。本文将从人力资源的…

【探索Linux】—— 强大的命令行工具 P.26(网络编程套接字基本概念—— socket编程接口 | socket编程接口相关函数详细介绍 )

阅读导航 引言一、socket 常见API表二、函数详细介绍01. socket()02. bind()03. listen()04. accept()05. connect()06. send()07. recv()08. close()09. select()10. getaddrinfo()11. sendto()12. recvfrom()13. setsockopt()14. getsockopt()15. shutdown()16. inet_pton()1…

【C语言】InfiniBand驱动mlx4_init和mlx4_cleanup

一、中文注释 Linux内核模块的初始化和清理过程&#xff0c;针对一个称为mlx4的网络设备驱动。以下是代码的逐行中文注释&#xff1a; static int __init mlx4_init(void) {int ret;if (mlx4_verify_params())return -EINVAL; // 检查设备参数是否有效&#xff0c;无效则返回…

管理者和员工之间缺乏有效的沟通,导致双方对绩效目标和期望存在误解,怎么办?

管理者和员工之间缺乏有效的沟通&#xff0c;导致双方对绩效目标和期望存在误解&#xff0c;这是绩效管理中一个常见且棘手的问题。这种沟通障碍可能源于多个方面&#xff0c;例如双方对绩效管理的理解不同、沟通方式不当或缺乏定期的沟通机制等。 当管理者和员工对绩效目标和…

AI产品摄影丨香水

AI电商产品拍摄丨&#xff08;可指定产品&#xff09; 均为概念图 可换产品 可指定产品&#xff0c;可换logo 工具&#xff1a;StartAI 搭配“手机摄影”风格使用效果更佳哦 咒语&#xff1a;anha perfume in bottle on stone surface, in the style of everyday american…

大运集团选用泛微数字化运营平台,构建丰富应用,业务协同

大运集团有限公司创建于1987年&#xff0c;位于山西省运城经济技术开发区&#xff0c;是集汽车、摩托车研发、制造、销售、服务及国际贸易、物流配送、工程建设等为一体的跨地区、跨行业、多元化发展的大型民营企业集团。 &#xff08;图片素材来自大运集团官网&#xff09; 集…

Linux内存映射

目录 背景 一、什么是内存映射&#xff1f; 二、mman函数 1.权限问题 2.总线错误 3.内存权限 4.读文件内容 5.映射与文件 6.非法参数错误 7.偏移量大小 8.映射内存大小 8.1 申请6k,访问5k 8.2 申请2k&#xff0c;访问3k 8.3 返回值检查 三、内存映射实现 四…