当前位置: 首页 > news >正文

【C++初阶】6. CC++内存管理

1. 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.代码段(常量区)
//globalVar在哪里?____   staticGlobalVar在哪里?____
//staticVar在哪里?____   localVar在哪里?____
//num1 在哪里?____
//
//char2在哪里?____ * char2在哪里?___
//pChar3在哪里?____ * pChar3在哪里?____
//ptr1在哪里?____ * ptr1在哪里?____
//2. 填空题:
//sizeof(num1) = ____;
//sizeof(char2) = ____;      strlen(char2) = ____;
//sizeof(pChar3) = ____;     strlen(pChar3) = ____;
//sizeof(ptr1) = ____;

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

【说明】

  1. 栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的。
  2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。
    (属于Linux相关模块,会在Linux博客中详细描述,现在仅需了解即可)
  3. 堆用于程序运行时动态内存分配,堆是可以上增长的。
  4. 数据段–存储全局数据和静态数据。
  5. 代码段–可执行的代码/只读常量

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

void Test()
{int* p1 = (int*)malloc(sizeof(int));free(p1);// 1.malloc/calloc/realloc的区别是什么?int* p2 = (int*)calloc(4, sizeof(int));int* p3 = (int*)realloc(p2, sizeof(int) * 10);// 这里需要free(p2)吗?free(p3);
}

这里的p2并不需要释放,因为若是空间不够realloc p3 会先释放p2原来的空间,再重新找一块空间
若是空间够,p3 和 p2 指向同一块空间

3. C++内存管理方式

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

3.1 new/delete操作内置类型

在这里插入图片描述
在这里插入图片描述
注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[]
注意:匹配起来使用。

3.2 new和delete操作自定义类型

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

关键点:

new和delete、malloc和free、new[ ] 和delete[ ] 必须要匹配使用
在这里插入图片描述
在这里插入图片描述

总结:

new / delete 相较于 malloc / free的优势在于:
1.new / delete会自动调用构造 / 析构函数,而malloc / free不会
2. new 不需要检查返回值来判断是否开辟成功,而malloc需要

4. operator new与operator delete函数(重点)

4.1 operator new与operator delete函数

底层new的实现:

  1. operator new ==》本质也就是经过封装的malloc
  2. 调用构造函数

new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

//以下为库中的operator new和operator delete的实现:
/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间
失败,尝试执行空               间不足应对措施,如果改应对措施用户设置了,则继续申请,否
则抛异常。
*/
void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{// try to allocate size bytesvoid* 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_FINALLYreturn;
}
/*
free的实现
*/
#define  free(p)               _free_dbg(p, _NORMAL_BLOCK)

C语言中的free是_free_dbg的宏定义,而C++中delete中也有_free_dbg

在这里插入图片描述

为啥要封装malloc,申请内存失败要报异常呢?因为这样才符合C++面向对象处理错误的方式
在这里插入图片描述

5. new和delete的实现原理

5.1 内置类型

如果申请的是内置类型的空间,new和malloc,delete和free基本类似
不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。

5.2 自定义类型

new的原理

  1. 调用operator new函数申请空间
  2. 在申请的空间上执行构造函数,完成对象的构造

delete的原理

  1. 在空间上执行析构函数,完成对象中资源的清理工作
  2. 调用operator delete函数释放对象的空间

new T[N]的原理

  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对 象空间的申请
  2. 在申请的空间上执行N次构造函数

delete[]的原理

  1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
  2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

对于operator new [ ] / operator delete [ ] 而言,最终调用的也是operator new / operator delete ,只不过是多次调用而已

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的区别(重点)

不能采用死记硬背的方式,要结合实例深刻理解

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在释放空间前会调用析构函数完成空间中资源的清理

7.2 内存泄漏

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

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

7.2.2 内存泄漏是内存丢了,还是指针丢了?

内存泄漏是指指针丢了该空间已经不需要再使用了(需要释放),但是找不到访问该空间的方法【形象的比喻:站着茅坑不拉屎】
而不是说内存丢了,操作系统的内存空间并未减少

7.2.3 如何避免内存泄漏?

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

总结一下:
内存泄漏非常常见,解决方案分为两种:1、事前预防型。如智能指针等。2、事后查错型。如泄漏检测工具。

相关文章:

【C++初阶】6. CC++内存管理

1. 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* …...

【数据结构】万字超详解顺序表(比细狗还细)

我这个人走得很慢,但是我从不后退。 ——亚伯拉罕林肯 目录 一.什么是线性表? 二.什么是顺序表? 三.接口函数的实现 1.创建工程 2.构造顺序表 3.初始化顺序表 3.初始化顺序表 4.顺序表的尾插 5.顺序…...

yolov5 剪枝、蒸馏、压缩、量化

文章大纲 剪枝推理优化YOLOv5 剪枝可能出现的问题参考文献与学习路径考察神经网络时期重要的激活函数sigmoid和tanh,它们有一个特点,即输入值较大或者较小的时候,其导数变得很小,而在训练阶段(详见1.2.3节),需要求取多个导数值,并将每层得到的导数值相乘,这样一旦层数…...

如何用python代码,更改照片尺寸,以及更换照片底色

前言 python浅浅替代ps?如何用代码来p证件照并且更换底色? 唉,有个小姐姐给我扔了张照片,叫我帮忙给她搞成证件照的尺寸还得换底色,她说自己忙的很 可惜电脑上没有ps只有pycharm,没得办法只能来试试看代…...

【pygame游戏】Python实现蔡徐坤大战篮球游戏【附源码】

前言 话说在前面,我不是小黑子~😏 本文章纯属技术交流~娱乐 前几天我获得了一个坤坤打篮球的游戏,也给大家分享一下吧~ 好吧,其实并不是这样的游戏,往下慢慢看吧。 准备工作 开发环境 Python版本:3.7.8 …...

通过指针引用字符串详解,以及字符指针变量和字符数组的比较

在平常的案例中已大量地使用了字符串,如在 printf函数中输出一个字符串。这些字符串都是以直接形式 (字面形式) 给出的,在一对双引号中包含若干个合法的字符。在本节中将介绍使用字符串的更加灵活方便的方法:通过指针引用字符串。 目录 一、…...

Vue基本整合(一)

NPM安装npm是node的包管理工具https://nodejs.org/en/脚手架安装npm i -g vue/clihttps://registry.npmjs.org/vue浏览器插件https://devtools.vuejs.org/guide/installation.html#chromehttps://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhble…...

C++编程之 万能引用

万能引用是一种可以同时接受左值或右值的引用,它的形式是T&&,其中T是一个模板参数。万能引用不是C的一个新特性,而是利用了模板类型推导和引用折叠的规则来实现的功能。 模板类型推导 模板类型推导是指在调用一个模板函数时&#x…...

【JavaScript速成之路】JavaScript内置对象--数组对象

📃个人主页:「小杨」的csdn博客 🔥系列专栏:【JavaScript速成之路】 🐳希望大家多多支持🥰一起进步呀! 文章目录前言数组对象1,数组类型检测2,数组元素增删3,…...

【华为机试真题详解 Python实现】最差产品奖【2023 Q1 | 100分】

文章目录 前言题目描述输入描述输出描述示例 1题目解析参考代码前言 《华为机试真题详解》专栏含牛客网华为专栏、华为面经试题、华为OD机试真题。 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即非性能…...

[算法] 二分查找

package com.guigu.search;import java.util.ArrayList; import java.util.Arrays;/*** author: guorui fu* versiion: 1.0* 二分查找 直接适用于已经排序完成的数组*/ public class BinarySearch {public static void main(String[] args) {int arr[] {1,8,8,89,101,1234};Ar…...

HTML面经

1.src与href的区别 src用于替换当前元素,如script标签,img标签等。当html解析到这些标签时,会暂停解析,将指定的资源下载下来,嵌入到所在位置内。href的话则是一个当前页面与引用资源之间的链接,如link标签…...

我的十年编程路 2021年篇

慢慢地,时光走过了8个年头,来到2021年。 站在2021年,回望8年的过往,没有大的起伏和波澜。或许是上天的眷顾,我的事业发展一直都很顺利。当然,弯路也走过一些,而且工作其实挺辗转的,…...

ElasticSearch 8 学习笔记总结(七)

感觉这些东西没必要认真学,了解一下,工作用到再学。 文章目录一、ES8 EQL 介绍二、ES8 EQL基本操作 与 安全检测三、ES SQL操作四、ES SQL与DSL的关系五、ES 常用的SQL操作六、ES datagrip配置ES七、ES8 自然语言处理 NLP八、ES8 性能优化 之 缓存九、ES…...

【云原生】Docker 网络模式详解、容器间网络通信

当项目大规模使用 Docker 时,容器通信的问题也就产生了。要解决容器通信问题,必须先了解很多关于网络的知识。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,也有着很多不完善的地方,网络方面就是 Docker…...

Java开发 - 布隆过滤器初体验

目录 前言 布隆过滤器 什么是布隆过滤器 布隆过滤器的作用 布隆过滤器原理 怎么设计布隆过滤器 布隆过滤器使用案例 安装布隆过滤器 添加依赖 添加配置 添加工具类 添加测试代码 简单测试 特别提醒​​​​​​​ 结语 前言 前面三篇,已经把消息队列…...

【计算机组成原理 - 第一章】计算机系统概论(完结)

本章参考王道考研相关课程: 【2021版】1.2.1_计算机硬件的基本组成_哔哩哔哩_bilibili 【2021版】1.2.2_认识各个硬件部件_哔哩哔哩_bilibili 【2021版】1.2.3_计算机系统的层次结构_哔哩哔哩_bilibili 【2021版】1.3_计算机的性能指标_哔哩哔哩_bilibili 目录 一、…...

C++类与对象(下)【详析】

类与对象(下) 目录类与对象(下)一、再谈构造函数1.构造函数体赋值2.初始化列表定义:注意点:总结:3.explicit关键字引入:explicit:二、 static成员回顾:static…...

exe反编译为.py文件

介绍公司以前的一个exe包,我们需要查看里面python源码,但是以前的py源码文件找不到,所以只能反编译,介绍一下反编译的过程。首先准备:pyinstxtractor.py这个文件,网上很多,自己下载准备查看二进…...

38 openEuler搭建FTP服务器-FTP总体介绍

文章目录38 openEuler搭建FTP服务器-FTP总体介绍38.1 FTP简介38.2 FTP使用到的端口38.3 vsftpd简介38 openEuler搭建FTP服务器-FTP总体介绍 38.1 FTP简介 FTP(File Transfer Protocol)即文件传输协议,是互联网最早的传输协议之一&#xff0…...

三天吃透操作系统面试八股文

本文已经收录到Github仓库,该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点,欢迎star~ Github地址:https://github.com/…...

vue后台管理系统——添加i18n国际化功能——技能提升

昨天在写后台管理系统时,遇到一个需求就是需要实现国际化功能。 antd和element-ui这两个框架其实都是有国际化的。 具体展示形式就是如下: 点击右上角头部的语言,切换语言,然后整个系统的文字都改变成对应的语言展示。 切换成…...

理清gcc、g++、libc、glibc、libstdc++的关系

0 理清gcc、g++、libc、glibc、libstdc++的关系 0.1 $ dpkg -L libc6 $ dpkg -L libc6 /lib/x86_64-linux-gnu /lib/x86_64-linux-gnu/ld-2.31.so /lib/x86_64-linux-gnu/libBrokenLocale-2.31.so /lib/x86_64-linux-gnu/libSegFault.so /lib/x86_64-linux-gnu/libanl-2.31.s…...

一、快速入门 MongoDB 数据库

文章目录一、NoSQL 是什么1.1 NoSQL 简史1.2 NoSQL 的种类及其特性1.3 NoSQL 特点1.4 NoSQL 的优缺点1.5 NoSQL 与 SQL 数据库的比较二、MongoDB 基础知识2.1 MongoDB 是什么2.2 MongoDB 的体系结构2.3 MongoDB 的特点2.4 MongoDB 键特性2.5 MongoDB 的核心服务和工具2.6 Mongo…...

PMP第一章到第三章重要知识点

第1章引论 1.1指南概述和目的 PMBOK指南收录项目管理知识体系中被普遍认可为“良好实践”的那一部分: “普遍认可”:大多数时候适用于大多数项目,获得一致认可。 “良好实践”:能提高很多项目成功的可能性。 全球项目管理业界…...

【事务与锁】当Transactional遇上synchronized

事务与锁 - Transactional与Synchronize🥰前言问题回放问题一1、代码与结果复现2、原因分析3、解决方法问题二1、问题复现2、原因分析事务Transactional与锁synchronized1、synchronized与Transactional区别2、可能带来的问题3、针对问题二的解决前言 最近工作中遇…...

Pytorch模型转TensorRT步骤

Pytorch模型转TensorRT步骤 yolov5转TRT 流程 当前项目基于yolov5-6.0版本,如果使用其他版本代码请参考 https://github.com/wang-xinyu/tensorrtx/tree/master/yolov5 获取转换项目: git clone https://github.com/wang-xinyu/tensorrtx.git git …...

产品经理入门——必备技能之【产品运营】

文章目录一、基础介绍1.1 用户生命周期 & 产品生命周期1.2 运营的目的1.3 运营的阶段1.4 运营的主要工作(海盗模型)二、AARRR模型2.1 Acquisition 拉新2.2 Activision 促活2.3 Retention 留存2.4 Revenue 转化2.5 Referral 传播总结产品运营技能是产…...

【Java实现文件上传】java后端+vue前端实现文件上传全过程详解(附源码)

【写在前面】其实这篇文章我早就想写了,只是一直被需求开发耽搁,这不晚上刚好下班后有点时间,记录一下。需求是excel表格的上传,这个是很多业务系统不可或缺的功能点,再此也希望您能够读完我这篇文章对文件上传不再困惑…...

什么是SSD?SSD简述

什么是SSD?SSD简述前言一. SSD组成二. SSD存储介质存储介质按材料不同可分为三大类:光学存储介质、半导体存储介质和磁性存储介质三. SSD接口形态固态硬盘有SATA 3.0接口、MSATA接口、M.2接口、PCI-E接口、U.2接口五种类型。三. SSD闪存颗粒分类闪存颗粒…...

wordpress获取当前文章分类/网推怎么推广

2016-10-14 16:35 来源:互联网 我来投稿 小程序创业扶持计划 实现月入10万创业梦 树莓派(Raspberry Pi)是基于ARM的微型电脑主板,外形只有信用卡大小,因此也被称为新型卡片式电脑,树莓派具有电脑的所有基本功能,可谓…...

建筑中级职称查询网站/网络广告营销的特点

本教程演示如何在 torchtext 中使用文本分类数据集,包括- AG_NEWS,- SogouNews,- DBpedia,- YelpReviewPolarity,- YelpReviewFull,- YahooAnswers,- AmazonReviewPolarity,- AmazonReviewFull此示例演示如何使用 TextClassification 数据集中的一个训练用于分类文本…...

国内网如何看国外网站/友情链接的作用

【考试简介】全国专业技术人员计算机应用能力考试是一种计算机能力考试。全国职称计算机考试可以提高计算机和网络的普及应用程度,加强信息资源的开发和利用”的精神,落实国家加快信息化建设的要求,引导全国专业技术人员学习掌握计算机知识&a…...

做网站vi系统是什么/百度网站客服

我采用得是STM32F10RC 参考得是STM32普中科技的给出得例子:https://www.bilibili.com/video/av30149282/?p45(这里给出网址) 1、基本介绍 包含有两个看门狗,独立看门狗:IWDG 窗口看门狗:WWDG 用来检测由…...

网站建设公司做前端/私人网站管理软件

1.1 问题 编写一个send_mail.py脚本,实现以下功能: 1.创建bob和alice帐户 2.编写发送邮件件程序,发件人为root,收件人是本机的bob和alice帐户 1.2 步骤 实现此案例需要按照如下步骤进行。 步骤一:创建bob和alice帐…...

北京微信网站制作/网推资源渠道

这里的讲解很不错&#xff0c;适合作为入坑题&#xff1a; Hihocoder#1938 代码&#xff1a; #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define ms(a,x) memset(a,x,…...