C/C++ 内存管理

C/C++ 内存管理

  • 1. C/C++内存分布
  • 2. C语言中动态内存管理方式:malloc/calloc/realloc/free
  • 3. C++内存管理方式
    • 3.1 new/delete操作内置类型
    • 3.2 new和delete操作自定义类型
  • 4. operator new与operator delete函数(重要点进行讲解)
    • 4.1 operator new与operator delete函数(重点)
  • 5. new和delete的实现原理
    • 5.1 内置类型
    • 5.2 自定义类型
  • 6. 定位new表达式(placement-new) (了解)
  • 7. 常见面试题
    • 7.1 malloc/free和new/delete的区别
    • 7.2 内存泄漏
      • 7.2.1 什么是内存泄漏,内存泄漏的危害
      • 7.2.2 内存泄漏分类(了解)
      • 7.2.3 如何检测内存泄漏(了解)
      • 7.2.4如何避免内存泄漏

1. C/C++内存分布

我们先来看下面的一段代码和相关问题
在这里插入图片描述

  1. char2 只是一个字符数组,因此存放在栈上。
  2. 星char2 在 栈上,因为数组名sizeof的时候代表整个数组,但是进行运算的时候,比如说解引用 它是代表首元素的地址。
    图示:
    在这里插入图片描述
    3.PChar3在栈上,首先const限制*PChar3,不能通过PChar3来修改PChar3指向的空间内容,但是指针变量PChar3可以改变,因此PChar3不可能在常量区。
  3. *PChar3 在常量区,原因如下:
    在这里插入图片描述
    4.指针变量ptr1在栈上,指向的内容在堆上,因此 * ptr 在堆上。
    在这里插入图片描述
    【说明】
  4. 又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的。
  5. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下)
  6. 用于程序运行时动态内存分配,堆是可以上增长的。
  7. 数据段–存储全局数据和静态数据。
  8. 代码段–可执行的代码/只读常量。

2. C语言中动态内存管理方式:malloc/calloc/realloc/free

在这里插入图片描述
【面试题】

  1. malloc/calloc/realloc的区别?
    malloc 函数用于分配指定大小的内存块,它从堆(heap)中分配内存,但不初始化这些内存。calloc 会将分配的内存初始化为零。realloc 函数用于扩容。
  2. malloc的实现原理? glibc中malloc实现原理

3. C++内存管理方式

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

3.1 new/delete操作内置类型

在这里插入图片描述
在这里插入图片描述
注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用。
例子:
在这里插入图片描述
new默认不初始化,但是它也可以初始化,如下:
在这里插入图片描述
注意 :对于内置类型开空间使用malloc或者new几乎是一样的

int* p3 = (int*)malloc(sizeof(int)); // C
int* p4 = new int;

3.2 new和delete操作自定义类型

在这里插入图片描述
注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。

4. operator new与operator delete函数(重要点进行讲解)

4.1 operator new与operator delete函数(重点)

new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
在这里插入图片描述
上面会有同学有疑问为什么要operator new,operator delete呢?直接调malloc不香吗?为啥要搞这个东西?有个原因在。首先malloc 失败的结果是什么?是返回空。所有以前用malloc的时候都会检查是否为空。new 呢? C++引出了一个叫异常的东西。通过上述两个全局函数的实现知道,operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的。
下面给你们看个new好用的代码:

在这里插入图片描述
为什么不是malloc+构造函数,而是operator new+函数构造,如果operator new 开空间失败了,malloc是返回0。operator new是封装(实际就是封装malloc),所以new失败抛异常实际上是在operator new开空间时(malloc+失败抛异常),从表层角度看malloc是一个函数的用法,new是一个操作符的用法。从底层角度看,new就是malloc,但是它在malloc的基础上加了很多东西,new其实比malloc多做了很多事情,多做了构造函数,失败了要抛异常。
还有个问题就是 new ,delete ,malloc ,free能不能混着使用,我这里建议大家配对使用。因为有时候能对,有时候可能程序会崩溃。混合使用可能导致释放位置不对。
在这里插入图片描述

5. new和delete的实现原理

5.1 内置类型

在这里插入图片描述

5.2 自定义类型

在这里插入图片描述
代码:
在这里插入图片描述

new底层原理图示:
在这里插入图片描述
delete底层原理图示:
在这里插入图片描述
析构 和 operator delete 释放的是不是同一个东西? 答案是:不是,operator delete delete的是谁?是p2指向的这块空间析构,析构是这个A对象上的资源的清理(当然是A对象有资源才需要清理,没有资源要清理,调用析构函数,就直接执行函数体的代码,比如说就只打印了一句)。
在这里插入图片描述

6. 定位new表达式(placement-new) (了解)

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
使用格式:

new (place_address) type或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表

使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

在这里插入图片描述

7. 常见面试题

7.1 malloc/free和new/delete的区别

在这里插入图片描述

7.2 内存泄漏

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

在这里插入图片描述
在这里插入图片描述

7.2.2 内存泄漏分类(了解)

在这里插入图片描述

7.2.3 如何检测内存泄漏(了解)

在vs下,可以使用windows操作系统提供的_CrtDumpMemoryLeaks() 函数进行简单检测,该函数只报出了大概泄漏了多少个字节,没有其他更准确的位置信息。
在这里插入图片描述
因此写代码时一定要小心,尤其是动态内存操作时,一定要记着释放。但有些情况下总是防不胜防,简单的可以采用上述方式快速定位下。如果工程比较大,内存泄漏位置比较多,不太好查时一般都是借助第三方内存泄漏检测工具处理的。

  • 在linux下内存泄漏检测:linux下几款内存泄漏检测工具
  • 在windows下使用第三方工具:VLD工具说明
  • 其他工具:内存泄漏工具比较

7.2.4如何避免内存泄漏

  1. 工程前期良好的设计规范,养成良好的编码规范,申请的内存空间记着匹配的去释放。ps:这个理想状态。但是如果碰上异常时,就算注意释放了,还是可能会出问题。需要下一条智能指针来管理才有保证。
  2. 采用RAII思想或者智能指针来管理资源。
  3. 有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功能选项。
  4. 出问题了使用内存泄漏工具检测。ps:不过很多工具都不够靠谱,或者收费昂贵。
    总结一下:
    内存泄漏非常常见,解决方案分为两种:1、事前预防型。如智能指针等。2、事后查错型。如泄漏检测工具。

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

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

相关文章

【Java】:洗牌功能和杨辉三角的实现

洗牌 此操作包含的基本功能有: 组牌:组建 52 张扑克牌 四种花色:“♥️”,“♠️”,“⬛️”,“♣️”每种花色 13 张牌:1~13 洗牌:将 52 张扑克牌打乱顺序发牌:给三个人…

【深度学习入门篇 ⑪】自注意力机制

【🍊易编橙:一个帮助编程小伙伴少走弯路的终身成长社群🍊】 大家好,我是小森( ﹡ˆoˆ﹡ ) ! 易编橙终身成长社群创始团队嘉宾,橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官…

C#进阶:深入理解异步编程与并发

在现代软件开发中,异步编程和并发控制是不可或缺的技能。随着应用程序变得越来越复杂,对性能、响应性和可扩展性的要求也越来越高。C#提供了强大的工具来支持异步编程和并发处理,如async和await关键字、Task Parallel Library(TPL…

Vue3 SvgIcon组件开发

在前面自定义tree组件继续功能迭代前,我们先开发一个通用的ScgIcon组件,用于后续组件模板中小图标的展示。 引入iconfont 官网:https://www.iconfont.cn/ 选取图标进行下载,只取iconfont.js文件 在prettier中忽略该文件&#x…

【YOLOv5/v7改进系列】引入CoordConv——坐标卷积

一、导言 与标准卷积层相比,CoordConv 的主要区别在于它显式地考虑了位置信息。在标准卷积中,卷积核在输入上滑动时,仅关注局部区域的像素强度,而忽略其绝对位置。CoordConv 通过在输入特征图中添加坐标信息,使得卷积…

【常用知识点-Linux】查询端口情况

Author:赵志乾 Date:2024-07-22 Declaration:All Right Reserved!!! 1. 简介 ss命令为socket statistics的缩写,是Linux的一个网络管理命令,主要用于获取系统中socket的统计信息&am…

[C/C++入门][for]26、统计满足条件的4位数(循环经典练习)

给定若干个四位数,求出其中满足以下条件的数的个数:个位数上的数字减去千位数上的数字,再减去百位数上的数字,再减去十位数上的数字的结果大于零。 【输入】 输入为两行,第一行为四位数的个数n,第二行为n个…

【SpringBoot】第3章 系统配置之日志配置

SpringBoot自带spring-boot-starter-logging库来实现系统日志功能,spring-boot-starter-logging组件默认使用LogBack日志记录工具。系统运行日志默认输出到控制台,也能输出到文件中。下面通过示例来演示SpringBoot项目配置日志的功能。 修改pom.xml文件…

校园招聘 之 Java HashMap

校园招聘与社会招聘在多个方面存在显著的区别,这些区别主要体现在招聘对象、招聘目的、招聘方式、招聘周期、招聘成本以及入职后的发展等方面。校招也更注重理论知识,俗称八股文,其实有些东西为什么一直拿来问,其实这里面你仔细品…

速盾:cdn技术实现原理是什么?

CDN技术(内容分发网络)是一种通过将内容部署到离用户更近的服务器上,从而提高网站访问速度和用户体验的技术。它的实现原理主要包括以下几个步骤: 域名解析:用户输入网址,浏览器首先向DNS服务器发送域名解析…

STM32CubeIDE(CAN)

目录 一、概念 1、简述 2、CAN 的几种模式 二、实践 1、环回模式轮询通信 1.1 软件配置 1.2 代码编写 2、环回模式中断通信 2.1 软件配置 2.2 代码编写 一、概念 1、简述 STM32微控制器系列包含多个型号,其中一些型号集成了CAN(Controller Are…

Vuex--全局共享数据

目录 一 是什么? 二 怎么用? 三 注意点 一 是什么? 在此之前,我们使用vue的数据全部放在每个组件的data区域里面,这里return里面存的都是这个组件要用到的数据,但是这里面的数据是局部的数据,也就是说这些数据是这…

Chrome v8 pwn 前置

文章目录 参考用到啥再更新啥简介环境搭建depot_tools和ninjaturbolizer 调试turbolizer使用结构数组 ArrayArrayBufferDataViewWASMJSObject结构Hidden Class命名属性-快速属性Fast Properties命名属性-慢速属性Slow Properties 或 字典模式Dictionary Mode编号属性 (Elements…

基于springboot+vue+uniapp的宿舍管理系统小程序

开发语言:Java框架:springbootuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包&#…

van-dialog 组件调用报错

报错截图 报错原因 这个警告表明 vue 在渲染页面时遇到了一个未知的自定义组件 <van-dialog>&#xff0c;并且提示可能是由于未正确注册该组件导致的。在 vue 中&#xff0c;当我们使用自定义组件时&#xff0c;需要先在 vue 实例中注册这些组件&#xff0c;以便 vue 能…

交易积累-AR

在股票交易分析中&#xff0c;AR&#xff08;Accumulation/Distribution Rating&#xff0c;积累/分配指标&#xff09;是一个反映股票在一定时期内被积累&#xff08;买入&#xff09;或分配&#xff08;卖出&#xff09;情况的指标。它是由美国著名的股票投资者威廉J奥尼尔&a…

本地搭建ros2环境步骤(x86_64架构)

验证效果&#xff1a;ros2跟redis能够相互通信&#xff0c;但不会接收到其它 orin 的 topic 消息&#xff1b;本地的话直接当作slave机器来用 注&#xff1a;ros2 的全局 param 需要依赖一个单点 redis-server&#xff0c;ros2 的全局 param 数据是保存在这个单点 redis-ser…

Json结构解析比较

文章目录 前言正文一、项目简介二、核心代码1、 JavaBeanParser2、 JsonStructCompare3、 Client 测试结果 前言 本次练习&#xff0c;主要是针对于两个Json的结构差异。 多用于测试场景&#xff0c;比如一个很大的Json报文&#xff0c;需要和现有的Json报文对比&#xff0c;看…

【快速逆向二/无过程/有源码】掌上高考—2024高考志愿填报服务平台

逆向日期&#xff1a;2024.07.21 使用工具&#xff1a;Node.js 加密工具&#xff1a;Crypto-js标准库 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 AES解密处理&#xff08;直接解密即可&#xff09;&#xff08;crypto-js.js 标准算法&…

百日筑基第二十八天-23种设计模式-行为型总汇

百日筑基第二十八天-23种设计模式-行为型总汇 文章目录 百日筑基第二十八天-23种设计模式-行为型总汇前言模板方法模式简介模板方式的特点模板方法模式结构类图模板方式模式案例分析模板方法模式应用源码分析模板方法模式的注意事项和细节 迭代器模式迭代器模式结构类图迭代器模…