【编译基础】new delete详解及内存泄漏

news2024/10/4 1:21:16

内存的使用,一文不太够

在这里插入图片描述



😊点此到文末惊喜↩︎

C++语言

1.new关键字

  1. 作用:C++通过new关键字动态分配内存
  2. 三种用法
    • plain new:最朴素的new,在使用new时编译器会申请内存,然后调用类的构造函数来初始化对象,调用delete会销毁对象同时释放该对象占用的内存,并且我们可以重载new操作符。但在空间分配失败的情况下,会抛出异常std::bad_alloc
    • nothrow new:在空间分配失败的情况下是不抛出异常,而是返回NULL。常用于服务器端内存不足时,不抛出异常而使程序终止,而是等待内存分配
    • placement new:
      • 原因:new操作符分配内存需要在堆中查找足够大的剩余空间,这个操作速度是很慢的,而且有可能出现无法分配内存的异常(空间不够)。
      • 解决方式:通过重载operator new复用已分配的原始内存空间,在该内存块上调用构造函数进行创建对象,所以对象销毁的时候不需要调用delete释放空间,但必须调用析构函数销毁对象。
      • 优点:用于需要反复创建并删除的对象上,可以有效降低分配释放内存的开销和碎片问题
class A
{
        int m_v;
public:
        A() {}
        A(int v) : m_v(v)  {}
        A(double v) : m_v(ceil(v)) {}
};
// plain new
        A* p1 = new A;           //非必要情况不会调用合成的构造函数
        A* p2 = new A();         //必然调用构造函数,如果没有,调用合成构造函数
        A* p3 = new A(3);        //调用int参数构造
        A* p4 = new A(3.1);      //调用double类型构造
        A* p5 = new A[2];        //分配2个元素数组,非必要不初始化
        A* p6 = new A[2]();      //分配2个元素,初始化
        A* p7 = new A[2](3);     //非法调用,动态分配数组不能指定带参数的构造函数
        //
        delete p1;
        delete p2;
        delete p3;
        delete p4;
        delete [] p5;
        delete [] p6;
// nothrow new
		p1 = new(nothrow) A;
		if(p1 == nullptr)
      		···;//等待并重试
// placement new
		// 调用nothrow进行内存实际分配
		char* p = new(nothrow) char[100];
		// 使用placement new进行该内存的复用
		long *q1 = new(p) long(100);
		int *q2 = new(p) int[100/sizeof(int)];
  1. 原理
    • new本质:调用operator new分配内存,将该内存进行转型后赋值给指针,然后调用构造函数进行赋值
    • operator new本质:尝试使用malloc进行分配内存,同时进行异常处理。可以重载,
// ### 调用new
Complex *pc = new Complex(1, 2);

// ### new的源码概括性解释
Complex *pc;
try{
    // 1.分配内存,实质调用malloc
    void *mem = operator new(sizeof(Complex));
    // 2.内存转型,赋值给指针
    pc = static_cast<Complex*>(mem);
    // 3.调用构造函数实例化内存(赋值)
    pc->Complex::Complex(1, 2);
    
}catch(std::bad_alloc){
    // 若allocation失败就不执行constructor
}

// ### operator new的源码概括性解释
// 第二参数保证函数不抛出异常
void *operator new(size_t size, const std::nothrow_t &){
    void *p;
    // 如果内存耗尽导致分配失败 (实质调用malloc)
    while((p=malloc(size)) == 0){
        _TRY_BEGIN
            if(_callnewh(size) == 0)// 调用自定义函数进行处理
                break;
        _CATCH(std::bad_alloc)
            return 0;
        _CATCH_END
    }
    return p;
}
  1. 注意事项
    • new分配的空间使用delete释放,new[] 使用 delete[]。
    • 如果重载了operator new,就应该也相应的重载operator delete

2.delete关键字

  1. 作用:
    • 释放new分配的动态内存:delete需要与new配对使用,其参数可以是指向一块内存首地址或空指针(nullptr)。不能对同一块内存多次delete,但是可以对空指针多次delete。
    • 阻止编译器合成函数:C++11以上,如果没有为类编写构造函数、析构函数、拷贝构造函数、拷贝赋值运算符,以及移动拷贝函数、移动赋值运算符,编译器可能会为类合成默认的函数版本。显式使用delete,可以阻止编译器合成对应函数。
class MyObj {
public:
	// 阻止编译器合成构造函数,会导致类无法实例化
  	MyObj() = delete; 
  	// 阻止编译器合成拷贝构造函数,会导致类无法拷贝构造,如cin, cout
  	MyObj& MyObj(const MyObj &) = delete;
  	// 阻止合成赋值运算符,会导致类无法拷贝,如cin, cout, cerr 
  	MyObj& operator=(const MyObj &) = delete; 
  ...
}

// default显式告诉编译器使用编译器自动合成的函数
class MyObj {
public:
	// 告诉编译器合成构造函数,作为默认构造函数,类的设计者不会实现该函数
  	MyObj() = default; 
  	// 告诉编译器合成拷贝构造函数,作为默认拷贝构造函数 
  	MyObj& MyObj(const MyObj &) = default;
  	// 告诉编译器合成赋值运算符 
  	MyObj& operator=(const MyObj &) = default; 
  ...
}


  1. delete的本质:先调用析构函数处理类对象,后调用operator delete函数进行内存的释放。operator delete函数本质是调用free函数
// delete的编译解释
delete pc;
pc->~Complex();// 先析构对象
operator delete(pc);// 后释放

//operator delete源码
void __cdecl operator delete(void *p)_THROW0(){
    free(p);
}
  1. new和delete的组合使用
// 动态申请/释放一个int类型的空间
int* ptr1 = new int;
delete ptr1;
// 动态申请/释放一个int类型的空间并初始化为10
int* ptr2 = new int(10);
delete ptr2;
// 动态申请/释放10个int类型的空间
int* ptr3 = new int[10];
delete[] ptr3;
  1. delete是如何获知需要释放的内存(数组)大小的?
    动态申请的内存块首部有cookie记录该块内存大小

C语言

1.malloc关键字

  1. 作用:
  2. 注意事项
    • new分配的空间使用delete释放,new[] 使用 delete[]。
  3. malloc/calloc/realloc之间区别
    • malloc函数:从堆上申请内存空间,必须使用memset初始化
    • calloc函数:从堆上申请内存空间并初始化为0
    • realloc函数:对已经存在的内存空间进行调整,如果更大会进行内存空间的延申,如果无法延申会申请新空间并拷贝和释放旧空间。如果更小会将原空间缩小。
    • 使用malloc函数,calloc函数和realloc函数分配的内存空间都要使用free函数指针参数为NULL的realloc函数来释放。?????????????????????

2.free关键字

区别

内存泄漏

什么是内存泄漏?

动态申请的资源,不使用了,也没有主动释放,就存在内存泄漏

//内存申请了没释放
int* a = (int*)malloc(sizeof(int));
int* b = new int;

//异常安全问题
int* c = new int;
fun()😕/如fun()函数抛异常,delete[] c未能执行,c没被释放
delete[] c;
1
2
3
4
5
6
7
8
内存泄漏的的危害

如果出现内存泄漏的进程正常结束,在进程结束时这些资源会自动归还系统,不会造成什么大的危害。
如果出现内存泄漏的进程正常结束(例如僵尸进程),则可用资源越来越少,系统会越来越慢,甚至卡死宕机。
需要长期运行的程序(服务器等),出现内存泄漏,系统会越来越慢,甚至卡死宕机。
如何避免?

事前预防。(如智能指针等)
事后查错。(使用泄漏检测工具等)
————————————————
版权声明:本文为CSDN博主「SimplexXx0」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/SimplexXx0/article/details/125702568


少年,我观你骨骼清奇,颖悟绝伦,必成人中龙凤。
秘籍(点击图中书籍)·有缘·赠予你


🚩点此跳转到首行↩︎

参考博客

  1. C++ new关键字详解
  2. 【C++】内存管理之new和delete
  3. C++中placement new操作符
  4. C++> delete关键字初探
  5. 待定引用
  6. 待定引用
  7. 待定引用
  8. 待定引用

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

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

相关文章

JdbcUtils工具类的优化升级——通过配置文件连接mysql8.0

我之前的博文JDBC重构——JdbcUtils工具类的封装写了一个JdbcUtils的工具类&#xff0c;但是这个类也会有一个问题&#xff1a;如下图所示&#xff1a;连接数据库的代码在java中是写死的&#xff0c;如果我们想要换一个数据库进行连接&#xff0c;就会很麻烦&#xff0c;这时我…

嵌入式HLS 案例开发手册——基于Zynq-7010/20工业开发板(2)

目 录 2 led_flash 案例 19 2.1 HLS 工程说明 19 2.2 编译与仿真 20 2.3 IP 核测试 23 3 key_led_demo 案例 23 3.1 HLS 工程说明 23 3.2 编译与仿真 25 3.3 IP 核测试 27 前 言 本文主要介绍 HLS 案例的使用说明,适用开发环境: Windows 7/10 64bit、Xilinx Vivado…

从零搭建的前后端完整的直播网页方案

前言&#xff1a;由于前段时间刚租了台服务器打算自己玩玩&#xff0c;随想首页或者哪哪个页面挂个我个人的直播间应该还挺有趣的。遂探索如何在我的网站上弄一个直播。三下五除二&#xff0c;清清爽爽&#xff0c;看完此文5分钟即可直播。 整体思路 最简单直观的图解。 由上图…

VB2019创建、使用静态库(同样的使用动态库dll)

库&#xff1a; 二进制可执行文件&#xff0c;操作系统载入内存执行&#xff0c;将不怎么更改的底层打包成库后可以使整体编译更改&#xff0c;并且实现对底层的保密&#xff08;不对外或员工开放&#xff09;。库有两种&#xff1a;静态库&#xff08;.a、.lib&#xff09;和动…

【国科大模式识别】第二次作业(阉割版)

【题目一】最大似然估计也可以用来估计先验概率。假设样本是连续独立地从自然状态 ωi\omega_iωi​ 中抽取的, 每一个自然状态的概率为 P(ωi)P\left(\omega_i\right)P(ωi​) 。如果第 kkk 个样本的自然状态为 ωi\omega_iωi​, 那么就记 zik1z_{i k}1zik​1, 否则 zik0z_{i…

【无标题】测试新发文章

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

Spring之后处理器

目录 一&#xff1a;概述 二&#xff1a;案例演示 三&#xff1a;Bean的后处理器----BeanPostProcessor 案例&#xff1a;对Bean方法进行执行时间日志增强 四&#xff1a;Spring ioc整体流程总结 一&#xff1a;概述 Spring的后处理器是Spring对外开发的重要扩展点、允许我…

量子计算机是什么?量子计算机和传统计算机之间有什么区别?

1.突破1000量子比特大关&#xff01; 2022年11月9日的IBM年度量子峰会上&#xff0c;IBM宣布了Osprey在量子硬件和软件方面取得的突破性进展&#xff0c;同时推出了“鱼鹰”&#xff08;Osprey&#xff09;芯片。“鱼鹰”是全球迄今为止量子比特最多的量子计算机&#xff0c;而…

软考初级信息处理

软考初级信息处理技术员还是比较简单的&#xff0c;只要多刷题&#xff0c;实操也很重要的&#xff01;备考时间讲究高效哦&#xff01; 1、考试安排&#xff1a; 2、关于信处的考点分析&#xff1a; 上午考试&#xff1a; 下午考试&#xff1a; 3、信处如何备考&#xff1a;…

从spark WordCount demo中学习算子:map、flatMap、reduceByKey

文章目录spark map和flatMap应用&#xff1a;Word CountreduceByKey的用法spark map和flatMap val rdd sc.parallelize(List("coffee panda","happy panda","happiest panda party"))&#xff08;1&#xff09;map rdd.map(_.split(" &q…

windows terminal 还是 cmder ?

前景提要 windows terminal自带的没有tab命令自动补全, cmd的自动补全垃圾; cmder虽然有自动补全, 但是界面管理不太行; 而且比较复杂&#xff1b;只想要其UI和路径换行显示; windows terminal 应用商城或https://github.com/microsoft/terminal 下载页 https://github.com/mic…

【算法刷题】哈希表题型及方法归纳

哈希表特点 常见的三种哈希结构&#xff1a; 1、数组&#xff1a;操作简单&#xff0c;方便快捷&#xff0c;但不适于进行一些更复杂的操作。 注&#xff1a;适用于用set或map的情景&#xff1a;&#xff08;1&#xff09;当数组大小受限&#xff1b;&#xff08;2&#xff0…

powerquery 连接 postgresql

1下载安装postgresql的驱动器 https://pan.baidu.com/s/1ii9PudUs9WL_clP7Ub647Q 提取码&#xff1a;hm6g 2 安装配置odbc 2.1打开控制面板 – 选择管理工具 2.2选择ODBC数据源(64位) 2.3控制面板搜索数据源-单击添加 选择postgresql unicode 2.4配置数据源信息 3.通过e…

einsum 理解

本文是参考以下两篇文章&#xff0c;再结合我自己的经验完成的&#xff1a; 文章一&#xff1a;https://zhuanlan.zhihu.com/p/358417772 文章二&#xff1a;https://zhuanlan.zhihu.com/p/27739282 Einsum介绍&#xff1a; 给定矩阵A 和矩阵B &#xff08;在Python中也可以说是…

【PCB专题】PCB板卡上的UL标识是什么?

PCB行业中重要的认证之一是UL认证。在网上直接搜索UL会出现很多与防火、安全、保险相关的词汇出现。

开发板测试手册——USB 4G 模块、GPS 定位功能操作步骤详解(3)

目录 4 USB 4G 模块测试 41 4.1 网络功能测试 42 4.2 短信功能测试 43 4.3 GPS 定位功能测试 44 4.4 通话功能测试 45 4.5 测试程序编译 46 5 USB 网口模块测试 47 前 言 本指导文档适用开发环境: Windows 开发环境: Windows 7 64bit 、Windows 10 64bit Linux 开…

C语言进阶内功修炼——深度剖析数据在内存中的存储

&#x1f412;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;别人可以拷贝我的模式&#xff0c;但不能拷贝我不断往前的激情 目录 &#x1f680;1. 数据类型介绍 &#x1f307;1.1 类型的基本归类&#xff1a; &#x1f680;2. 整形在内存中的存储 &am…

Three.js学习(一)three.js的一些基本操作

文章目录1.鼠标操作三维场景旋转、移动和缩放2.场景中添加新的三维图形3.设置材质效果4.光源效果1.鼠标操作三维场景旋转、移动和缩放 使用THREE的OrbitControls控件&#xff0c;可以实现鼠标控制三维图形的操作。主要是通过监听鼠标操作&#xff0c;控制相机的三维参数。 imp…

在线问诊呈爆发式增长,聚合支付分账如何助力互联网医疗平台加速发展?

&#xff08;图源:pexels网站&#xff09; 随着疫情的放开&#xff0c;人们问诊需求快速上涨&#xff0c;由于医院服务的压力激增&#xff0c;线上问诊成为了不少人替代去医院的有效手段&#xff0c;甚至于线上问诊开始出现了爆发式增长。但是在互联网医疗平台的发展过程中&am…

C语言进阶——数据的存储

目录 一. 数据类型 二. 整形在内存中的存储 1.原码、反码、补码 2.大小端 三. 浮点型在内存中的存储 存储 取出 一. 数据类型 在前面&#xff0c;我们已经学过一些基本的内置类型 char——字符数据类型 short——短整型 int——整形 long——长整形 long…