【C++】内存管理

目录

C/C++内存分布

C语言中动态内存管理方式

C++内存管理方式

operator new与 operator delete函数

匹配使用的相关问题-内存泄漏:

delete与delete [ ]

malloc/free和 new/delete的区别

内存泄漏


C/C++内存分布

  1. 又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。

  2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口 创建共享共享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下)

  3. 用于程序运行时动态内存分配,堆是可以上增长的。

  4. 数据段--存储全局数据和静态数据。

  5. 代码段--可执行的代码/只读常量

C语言中动态内存管理方式

具体讲解:C语言:动态内存管理(动态内存+柔性数组讲解)_努力学c的楼下小王的博客-CSDN博客

int * p1=(int*)malloc(sizeof(int));
if(p1==NULL)
{
  perror("malloc is fail");
}
free(p1);

C++内存管理方式

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

注意:申请和释放单个元素的空间,使用new和delet操作符,申请和释放连续的空间,使用new[]delete[],注意:匹配起来使用。 也切勿使用C语言中的free或malloc等与C++中的new和delete交叉使用 否则导致结果是不确定的

operator new与 operator delete函数

注意! 此处的operator 并不是函数重载,而是库函数

operator new与 operator delete本质上是malloc和free的封装

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

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

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


 int main()
 {
     //申请失败会抛出异常
     int *p1 = (int *)operator new(sizeof(int *));
     
     //失败返回nullptr
     int *p2 = (int *)malloc(sizeof(int *));
     if (p2 == NULL)
     {
         perror("malloc is fail");
     }
 ​
     return 0;
 }
 // 申请空间 operator nwe -> 封装malloc
 // 调用构造函数
 A *p3 = new A;
 ​
 // 先调用析构函数,在释放p3指向的空间
 delete p3;
 ​
 // 申请空间: operator new[]-> operator new -> malloc封装
 A *p4 = new A[10];
 ​
 // 先调用10次析构函数,在释放p4指向的空间
 delete[] p4; //[]只是为了匹配
匹配使用的相关问题-内存泄漏:

由前文可知,C++中的new与delete和C中的mlloc.. 和free尽量不要交叉使用 看下列代码:

 class A
 {
 public:
     A(int a = 0)
         : _a(a)
     {
         cout << "A():" << this << endl;
     }
     ~A()
     {
         cout << "~A():" << this << endl;
     }
 ​
 private:
     int _a;
 };
 int main()
 {
     int *p1 = new int[10];
     free(p1);
 ​
     A *p2 = new A;
     free(p2);
 ​
     return 0;
 }

此处并没有报错,若是使用delete p2时,则会先调用析构函数再进行free

而此处直接使用free 释放,释放的是堆上的空间,但少调用了析构函数, 但此处也无需调用析构函数,A类中并没有额外的资源需要进行清理, 若是A类中有需要额外清理的则会导致内存泄漏如:

 class Stack
 {
 private:
     int* _a;
     int _size;
     int _capacity;
 ​
 public:
     Stack()
     {
         cout << "Stack():" << this << endl;
         _a=new int[4];
         _size=0;
         _capacity =4;
     }
 ​
     ~Stack()
     {
         cout << "~Stack():" << this << endl;
         delete[] _a;
         _size=_capacity=0;
     }
 };
 ​
 int main()
 {
     //st为自定义类型,出了函数会自动调用析构函数
     Stack st;
 ​
     //pst为指针,是内置类型,不会自动调用
     Stack* pst=new Stack;
     delete pst;
 ​
     return 0;
 }

由上图可以看出,pst必须先调用析构函数将堆中创建的空间进行销毁:

调用完析构函数后,再调用operator delete(pst):

若此时使用的是free(pst): 则导致无法调用析构函数,无法释放空间,而pst指针指向的空间被销毁,而之前通过 new 分配的内存将无法被正确释放导致内存泄漏

结论:new/malloc系列 底层实现机制有关联交叉.不匹配使用,可能有问题,也可能没问题

delete与delete [ ]

部分编译器会实现该机制或不同编译器实现机制不同

 int main()
 {
     A* p1=new A[10];
     delete[] p1;
 ​
     return 0;
 }

编译器会在头部多开4字节,存储数组元素个数,用于delete,使编译器知道要调用多少次析构函数(此处地址为p1地址-4字节):

malloc/freenew/delete的区别

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需

    要捕获异常

  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new

    在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成 空间中资源的清理

内存泄漏

什么是内存泄漏,内存泄漏的危害

什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。 内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。

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

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

相关文章

人工智能引领环境保护的新浪潮:技术应用及其影响

在全球范围内&#xff0c;环境保护已经成为一个迫切的话题。随着人工智能技术的发展&#xff0c;它开始在环境保护领域扮演越来越重要的角色。AI不仅能够帮助更有效地监测环境变化&#xff0c;还能提出解决方案来应对环境问题。 污染监测与控制&#xff1a; AI系统可以分析来自…

redis运维(十)列表

一 列表 强调&#xff1a; 知道原生redis具备的能力,以便后续API调用 ① 基础概念 备注&#xff1a; 单个list最多2^32-1个元素 列表操作常用命令,涉及&#xff1a;CURD ② lpush 左插入 说明&#xff1a; 如果key不存在就会初始化,否则就是插入元素备注&#xff1a; l…

指针——C语言初阶

一.指针基本概念&#xff1a; 指针是内存中一个最小单元的编号&#xff0c;也就是地址平时口语中说的指针&#xff0c;通常指的是指针变量&#xff0c;是用来存放地址的变量 #include<stdio.h> int main() {int a 0;//a是整型变量&#xff0c;占用四个字节的内存空间&a…

Linux系统(CentOS7)上安装MYSQL8.x

Linux系统是CentOS7版本&#xff0c;今天在新电脑上安装MYSQL&#xff0c;跟着网上的文章&#xff0c;尝试了好几次&#xff0c;都是启动失败&#xff0c;删了安&#xff0c;安了删&#xff0c;搞了一下午&#xff0c;头昏脑胀&#xff0c;网上的一些文章太乱了&#xff0c;每种…

SSM框架

SSM SSM框架说明SpringBootMyBatis整合MyBatis数据库中表的设计Pojo对象设计Dao接口设计Dao单元方法进行测试 XML管理整合MyBatis框架映射配置文件的位置XML配置SQL标签常用的SQL标签 动态SQL语句动态删除数据动态修改数据 SSM框架说明 Spring 指 Spring Framework&#xff0c…

前段-用面向对象的方式开发一个水管小鸟的游戏

首先准备好各类空文件 index.js css html 和图片 图片是下面这些&#xff0c;如果没有的可在这里下载 2 开发开始 好了&#xff0c;基础准备工作完毕&#xff0c;开发开始&#xff0c; 首先&#xff0c;先把天空&#xff0c;大地&#xff0c;小鸟的盒子准备好&#xff0c;并…

Redis数据库双写一致性解决方案

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

好用的企业防泄密软件盘点

企业防泄密软件是专门设计用于保护企业敏感信息不被泄露的软件产品。这类软件通常采用多种安全技术和策略&#xff0c;以增强企业数据的安全性和保密性&#xff0c;防止核心知识产权和商业机密的泄露。 企业防泄密软件的主要功能包括数据加密、访问控制、审计和监控、文件和数据…

CSS样式穿透

当我们在vue项目中使用第三方组件时&#xff0c;有时候需要去修改某些元素的样式&#xff0c;但有时写的css样式不会覆盖组件的样式&#xff0c;所以要用到样式穿透。 常用的方法有这几种&#xff1a;&#xff08;1&#xff09;>>> &#xff08;2&#xff09;/deep/ …

flink中配置Rockdb的重要配置项

背景 由于我们在flink中使用了状态比较大&#xff0c;无法完全把状态数据存放到tm的堆内存中&#xff0c;所以我们选择了把状态存放到rockdb上&#xff0c;也就是使用rockdb作为状态后端存储,本文就是简单记录下使用rockdb状态后端存储的几个重要的配置项 使用rockdb状态后端…

电子器件系列44:环形线圈电感

干货&#xff01;电感最重要、最常见的几个作用_线圈 环形线圈电感的原理&#xff1a; 电感中包含了哪三个物理学定律&#xff0c;为什么它能以磁场形式储能_哔哩哔哩_bilibili 电感的基本原理_哔哩哔哩_bilibili 环形线圈电感的作用: 1.储能器&#xff1a; 环形线圈电感能够…

【Python大数据笔记_day10_Hive调优及Hadoop进阶】

hive调优 hive官方配置url: Configuration Properties - Apache Hive - Apache Software Foundation hive命令和参数配置 hive参数配置的意义: 开发Hive应用/调优时&#xff0c;不可避免地需要设定Hive的参数。设定Hive的参数可以调优HQL代码的执行效率&#xff0c;或帮助定位问…

005.存储管理

使用硬盘设备前需要对其进行分区、格式化&#xff0c;分区可以使公司业务数据得到更有效的管理。我们需要提前规划好硬盘的存储空间&#xff0c;至于一块硬盘到底要分多少个区&#xff0c;每个分区预留多大空间&#xff0c;这需要根据文件数量、大小、类型等进行对应的设计。有…

c语言:解决判断两个字符串是不是互为旋转字符的问题

题目&#xff1a; 思路&#xff1a;先判断两个字符长度是否相等&#xff0c;如果不相等&#xff0c;肯定不是互为旋转字符串。 方法一&#xff1a;将第一份字符串右旋0-n&#xff08;字符个数&#xff09;次&#xff0c;判断是否有一次右旋完的字符串等于第二个字符串。如果有&…

MIKE水动力笔记19_统计平均潮差

本文目录 前言Step 1 ArcGIS中创建渔网点Step 2 将dfsu数据提取到渔网点Step 3 Python统计平均潮差 前言 日平均潮差&#xff08;average daily tidal range&#xff09;&#xff1a;日高潮潮高合计之和除以实有高潮个数为日平均高潮潮高&#xff0c;日低潮潮高合计之和除以实…

剑指offer(C++)-JZ39:数组中出现次数超过一半的数字(算法-其他)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 给一个长度为 n 的数组&#xff0c;数组中有一个数字出现的次数超过数组长度的一半&#xff0c;请找出这个…

Taro.navigateTo 使用URL传参数和目标页面参数获取

文章目录 1. Taro.navigateTo 简介2. 通过 URL 传递参数3. 目标页面参数获取4. 拓展与分析4.1 拓展4.2 URL参数的类型4.3 页面间通信 5. 总结 &#x1f389;欢迎来到Java学习路线专栏~Taro.navigateTo 使用URL传参数和目标页面参数获取 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x…

C语言--写一个函数返回bool值,来判断给定的字符串A和B(假设都是小写字母),是否是B中的字符都存在于A中,如果是返回true,否则返回false

一.题目描述 写一个函数返回bool值&#xff0c;来判断给定的字符串A和B&#xff08;假设都是小写字母&#xff09;&#xff0c;是否是B中的字符都存在于A中&#xff0c;如果是返回true&#xff0c;否则返回false。例如&#xff1a; 字符串A&#xff1a;abcde 字符串B&#xff…

搭建yum源并定时同步

一 、安装yum源 1-准备yum目录 cd /data/www/html createrepo -v ./目录 2-安装服务 yum -y install httpd 3-配置服务 /etc/httpd/conf/httpd.conf 4.配置/etc/yum.repo.d/local.rpeo 二、定时更新yum源 #1. 同步整个源到指定目录 [rootV10SP1-1 pac]# reposync -p /root/…

井盖位移监测,智能井盖传感器

在每一个繁华的城市背后&#xff0c;总是有一些默默无闻的英雄。这些英雄或是人或是物&#xff0c;对城市未来建设和城市生命线来讲意义重大。其中井盖作为不可或缺的一部分&#xff0c;默默守护着道路安全与公共安全。它的状态却直接关系到我们的生活便利与安全。近年来随着科…