C++内存管理机制(侯捷)笔记4(完结)

news2024/10/2 20:37:14

C++内存管理机制(侯捷)

本文是学习笔记,仅供个人学习使用。如有侵权,请联系删除。

参考链接

Youtube: 侯捷-C++内存管理机制

Github课程视频、PPT和源代码: https://github.com/ZachL1/Bilibili-plus

介绍

下面是第四讲和第五讲的笔记。

第四讲:loki库的allocator

第五讲:other issues,主要介绍GNU C++提供的其他分配器的使用

截至2024年1月12日,花费3天时间完成《C++内存管理——从平地到万丈高楼》的学习。

文章目录

  • C++内存管理机制(侯捷)
    • 介绍
    • 45 上中下三个classes分析
    • 46 Class Chunk分析
    • 47 class FixedAllocator分析(上)
    • 48 class FixedAllocator分析(下)
    • 49 Loki::allocator总结
    • 50 GNU C++对allocators的描述
    • 51 VS2013标准分配器&G4.9标准分配器与new_allocator以及G4.9malloc
    • 52 G4.9array_allocator
    • 53 G4.9 debug_allocator
    • 54 bitmap_allocator上
    • 55 bitmap_allocator(下)
    • 后记

45 上中下三个classes分析

loki的allocator

Loki 是 C++ 中一个开源的库,其中包含一组通用的 C++ 组件。在 Loki 库中,有一个称为 Loki::Allocator 的组件,它是一个用于内存分配的工具。

讲这个分配器是为了和GNU C++中的alloc分配器作比较,alloc分配器最后的内存并没有还给操作系统。

Loki allocator的三个类,从低阶到高阶分别为:Chunk, FixedAllocator, SmallObjAllocator。

在这里插入图片描述

Chunk

pData_: unsigned char* // 指针,指向分配的一个chunk
firstAvailableBlock_:unsigned char // 第一个可用区块
blocksAvailable_: unsigned char // 目前还可以供应几个区块

FixedAllocator

chunks_: vector<Chunk> // vector里面放了很多chunk
// 两个指针,指向某两个Chunk
allocChunk_: Chunk* 
deallocChunk_: Chunk*

SmallObjAllocator

pool_: vector<FixedAllocator>  // 里面放了很多FixedAllocator
// 两个指针,指向某两个FixedAllocator
pLastAlloc: FixedAllocator*
pLastDealloc: FixedAllocator*
chunkSize: size_t
maxObjectSize: size_t

46 Class Chunk分析

Loki allocator里面的Chunk

Init函数:new调用malloc创建对象,分配一大块chunk

调用Reset函数,下图中可用的block个数为64,第一个可以的block的编号为0,然后一个for循环,把每个block的第一个字节当作索引index使用(类似于嵌入式指针)

还有Release函数,使用delete[],释放空间,还给操作系统。

在这里插入图片描述

Chunk的Allocate函数

分配一个可用区块(最高优先权),然后firstAvailableBlock_指向下一个可用区块,比如这里可用区块的索引从左边的4变成了右边的3,剩余区块个数也相应调整。

在这里插入图片描述

Chunk的Deallocate函数

释放的指针p已经确定在这个Chunk中,但是p是这个Chunk中的第几个block呢?用p指针减去头指针然后除以每个block的大小,得到该释放的block的索引,这个释放回收的块block具有最高优先权,成为firstAvailableBlock_,然后可利用的block个数+1.

在这里插入图片描述

47 class FixedAllocator分析(上)

FixedAllocator

chunks_: vector<Chunk> // vector里面放了很多chunk
// 两个指针,指向某两个Chunk
allocChunk_: Chunk* 
deallocChunk_: Chunk*

allocChunk_指向最近一次满足分配动作的Chunk,deallocChunk _指向最近一次回收的Chunk。因为有很多chunk,要指定最近用过的chunk,这符合数据的局部性原理。

Allocate的逻辑如下图所示:如果有最近的allocChunk_,那么直接取区块,否则就要for循环从头开始遍历每个chunk,直到找到有可用空间的chunk。return allocChunk->Allocate(blockSize_);是向这个chunk取区块。

在这里插入图片描述

48 class FixedAllocator分析(下)

第二级FixedAllocator类的Deallocate函数,调用VicinityFind函数查找还回来的指针p落在哪个chunk,找到之后交给第一级Chunk类的Deallocate来处理。

VicinityFind(临近搜寻)函数如下:功能是进行查找。

chunkLength是chunk的大小,后面查找的时候要用

lo是上次还回来的chunk,hi是下一个chunk

loBound和hiBound是vector的头跟尾

整体思路是:并分两路,一路往上查找,一路往下查找。

在lo里面找,找不到的话就往上面的chunk去查找,一直往上,一个接一个的chunk去找。

然后在hi里面找,找不到就往下面的chunk去查找,一直往下,一个接一个的chunk去找。

在这里插入图片描述

下面是FixedAllocator类的DoDeallocate函数

调用Deallocate函数进行回收,然后确认是否是全回收的情况处理。

全回收的时候,需要确认有2个chunk,才回收一个,就是上文讲到的deferring延缓回收。

在这里插入图片描述

49 Loki::allocator总结

很简单的方式判断chunk全回收,指的是记录可用区块个数,当它变成0的时候表示全分配出去,当它恢复到原来的状态,就表示可全回收。

在这里插入图片描述

50 GNU C++对allocators的描述

第五讲 other issues

GNU C++ 对于allocator的描述

在这里插入图片描述

下面介绍两个分配器: new_allocator 和malloc_allocator,它们都没有特别的动作,无非底部调用operator new和malloc。它们没有用内存池。

在这里插入图片描述

另一种做法是使用智能型的allocator,使用内存池,分一大块然后切分成小块。

这类allocator有bitmap_allocator, pool_allocator, _mt_alloc(multithread多线程的分配器)

在这里插入图片描述

GNU C++ 提供三种测试,用于测速:插入数据测试,多线程状态下的插入和删除测试,多线程的生产者和消费者模型测试。

在这里插入图片描述

另外两个智能型allocator是 debug_allocator 和 array_allocator

在这里插入图片描述

51 VS2013标准分配器&G4.9标准分配器与new_allocator以及G4.9malloc

VS2013版本的标准分配器allocator,里面的allocate函数就是调用operator new,底层调用malloc,这是一种没有包装的分配器。

在这里插入图片描述

GNU C++4.9版本的标准分配器 allocator,继承自new_allocator,里面的动作也是operator new 和operator delete,也是没有包装的分配器。

在这里插入图片描述

GNU C++4.9版本的malloc_allocator,里面就是调用malloc和free,没有包装。

在这里插入图片描述

52 G4.9array_allocator

array_allocator

指针_M_array指向一个C++数组,静态数组不需要释放,归还

在这里插入图片描述

看看array_allocator怎么使用

int my[65536];
array_allocator<int, array<int, 65536>> myalloc(&my); // 传入数组的地址

在这里插入图片描述

第二种用法,是用动态的new一块数组,其他用法与上面一致。

在这里插入图片描述

53 G4.9 debug_allocator

debug_allocator是一个包装器,把另一个分配器包装进来,这里是_Alloc分配器,定义为_M_allocator,实际分配的时候就是调用这个分配器的allocate,分配n + extra个大小的空间。

在这里插入图片描述

GNU C++2.9容器使用的不是std::allocator,而是std::alloc,这是一个好的分配器。

在这里插入图片描述

在GNU C++4.9版本的__pool_alloc就是上面2.9版本的alloc。它的缺点是什么呢?只拿不还,不把分配的空间还给操作系统。

在这里插入图片描述

GNU C++4.9版本 __pool_alloc测试用例

在这里插入图片描述

54 bitmap_allocator上

这里重要的是_M_allocate_single_object_M_deallocate_single_object,这是什么意思呢?所有的allocator都是供给容器使用的,容器每次请求的都是一个元素的内存分配,所以这里就是单独处理一个object的请求。当不是一个object的时候,就会退化到operator new和operator delete,但是这种情况一般遇不到。

在这里插入图片描述

当客户是容器的使用,容器要的一个元素的内存空间就是block,如果是std::list的时候,这个block还包括node里面的指针。

下图中64blocks指的是一次性挖64个blocks开始供应,这个是两倍成长,下次挖128个,再是256个,…

挖的这些blocks,加上前面的bitmap,还有前面的数值,一起称为super block。

bitmap中是64bits(对应于blocks的数量),每个bit表示单个block的状态,bitmap是unsigned int,一个bitmap是32位,只能记录32个blocks的情况。这里是64个blocks,需要2个bitmap来记录。

前面还有一个整数use count,记录有几个block被分配

最前面还有一个整数,记录super block的大小

有一个mini vector(模拟标准库中的vector写出来的)来操纵super block,里面的start指针和finish指针分别指向super block的头和尾

在这里插入图片描述

现在客户需要分配内存:下面深灰色这个block被分配出去,use count = 1,然后bitmap[0]最后一位变成0,表示已经分配出去

在这里插入图片描述

然后请求分配第二个block,下面两个灰色的block表示被分配出去,use count = 2,bitmap[0]后两位变成0,表示这两个block被分配出去。

在这里插入图片描述

后面一直分配block出去,下图表示已经分配出去63个block,对应的use count = 63,bitmap[1]和bitmap[0]变成80000000H和00000000H,只有最后一个block对应的bitmap中的bit才为1,表示未被分配出去。

在这里插入图片描述

下面客户归还其中一个block,对应的bitmap要变成1,表示未分配(回收回来),然后use count由63变成62

在这里插入图片描述

当1个super block(有64个blocks)用完后,开始启用第二号super block,这时候super block中的block块数由64扩大两倍变成128个,由4个bitmap整数表示。

而且mini vector中由一个单元,变成两个单元,每个单元指向一个super block。

在这里插入图片描述

第二个super block用完(前面已经用完第一个super block,其含有64个blocks,第二个super block包含128个blocks,也已经用完),启用第三个super bloc,其包含的blocks为128 x 2 = 256个。

mini vector中也有第三个单元来控制这个super block。

在这里插入图片描述

55 bitmap_allocator(下)

上面谈的是bitmap_allocator的分配,下面谈它的回收(容器归还元素空间)机制

第一个super block全回收,用另一个mini vector(称为free list)中的entry指针指向这个super block,表示已经回收。

如果下次新分配一个super block,它其中blocks的数量要减半,如下图所示,如果前三个superblocks大小分别为64个,128个,256个,由于第一个superblock被回收,那么下次分配的superblock大小由已经分配的最大值256变成一半,为128个blocks。

原来的mini vector里面的指向回收的这个superblock头和尾的entry被删除。

在这里插入图片描述

第二个super block也全回收,则free list里的entry加一个,指向这个super block。

原来的mini vector里面指向这个superblock头尾的entry被删除。

在这里插入图片描述

第三个super block被全回收,被free list的指针指向。

在这里插入图片描述

后记

截至2024年1月12日22点09分,完成《C++内存管理机制》的第四讲和第五讲的笔记。主要涉及Loki库中allocator的设计,以及对GNU C++4.9其他allocator的介绍,主要包含bitmap_allocator。

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

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

相关文章

STM32F103RCT6开发板M3单片机教程07-TIMER1CH1输出 PWM做LED呼吸灯

概述 本教程使用是&#xff08;光明谷SUN_STM32mini开发板&#xff09; 免费开发板 在谷动谷力社区注册用户&#xff0c;打卡&#xff0c;发帖求助都可以获取积分&#xff0c;当然最主要是发原创应用文档奖励更多积分&#xff0e; (可用积分换取&#xff0c;真的不用钱&…

Mysql InnoDB行锁深入理解

Record Lock记录锁 Record Lock 称为记录锁&#xff0c;锁住的是一条记录。而且记录锁是有 S 锁和 X 锁之分的&#xff1a; 当一个事务对一条记录加了 S 型记录锁后&#xff0c;其他事务也可以继续对该记录加 S 型记录锁&#xff08;S 型与 S 锁兼容&#xff09;&#xff0c;…

NAND SCA接口对性能影响有多大?

在多LUN场景下&#xff0c;SCA接口尤其有助于提高随机读取性能。通过合理安排读取命令和等待时间&#xff08;如tR&#xff09;&#xff0c;SCA接口可以在一个LUN完成读取后立即开始另一个LUN的读取操作&#xff0c;而无需等待整个DQ总线空闲&#xff0c;从而减少了延迟和提高了…

设计一个简易版的数据库路由

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术&#x1f525;如果感觉博主的文章还不错的…

双指针问题——求只包含两个元素的最长连续子序列(子数组)

一&#xff0c;题目描述 你正在探访一家农场&#xff0c;农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示&#xff0c;其中 fruits[i] 是第 i 棵树上的水果 种类 。 你想要尽可能多地收集水果。然而&#xff0c;农场的主人设定了一些严格的规矩&#xff0c;你必…

vue前端开发自学,组件的生命周期函数介绍001

vue前端开发自学,组件的生命周期函数介绍001&#xff01;今天介绍一下&#xff0c;组件自身的生命周期函数。又叫做&#xff0c;钩子函数。可以借助于这些钩子函数&#xff0c;实现很多我们预想的效果。比如&#xff0c;在组件渲染 之前&#xff0c;就做一些特殊的操作等等。 …

什么是 CAS

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

Javaweb之SpringBootWeb案例查询部门以及前后端联调的详细解析

2.1 查询部门 2.1.1 原型和需求 查询的部门的信息&#xff1a;部门ID、部门名称、修改时间 通过页面原型以及需求描述&#xff0c;我们可以看到&#xff0c;部门查询&#xff0c;是不需要考虑分页操作的。 2.1.2 接口文档 部门列表查询 基本信息 请求路径&#xff1a;/depts …

内存卡为什么会提示格式化,内存卡提示格式化还能恢复吗

对于许多电脑用户来说&#xff0c;执行内存卡格式化操作导致数据丢失是一个常见的问题。在日常生活中&#xff0c;数据丢失的情况并不少见&#xff0c;但内存卡格式化后的数据恢复相对较难。目前&#xff0c;能够使用的方法较少&#xff0c;且成功率较低&#xff0c;但并不是没…

NAND系统性能提升常见方案

随着NAND的发展&#xff0c;针对NAND系统性能提升&#xff0c;业内目前主要的做法有以下几种方案&#xff1a; 1.提升总线频率和优化AC时序&#xff1a; 提高NAND闪存接口的工作频率可以显著加快数据传输速度。通过不断改进工艺和技术&#xff0c;缩短了信号稳定时间、降低了延…

Linux第29步_虚拟机连接(与主机断开连接)U盘选项为灰色解决方法

在WIN11中&#xff0c;虚拟机“连接(与主机断开连接)U盘”选项为灰色&#xff0c;解决方法如下&#xff1a; 1、关闭虚拟机电源&#xff0c;得到下面的界面&#xff1a; 2、根据上述提示&#xff0c;找到虚拟机所在磁盘 3、配置文件属性见下图&#xff1a; 4、使用记事本打开…

vim基本操作命令

一、vi简介 vi是“Visual interface”的简称&#xff0c;它在Linux上的地位就仿佛Edit程序在DOS上一样。它可以执行输出、删除、查找、替换、块操作等众多文本操作&#xff0c;而且用户可以根据自己的需要对其进行定制。Vi不是一个排版程序&#xff0c;它不象Word或WPS那样可以…

“具身智能”浪潮中,达闼机器人的商业化“奇点”已然到来?

当前&#xff0c;人形机器人产业正在快速发展&#xff0c;而2023年必将会是载入史册的一年。 具体来看&#xff0c;2023年&#xff0c;AI技术大爆发&#xff0c;可在语言、视觉、运动控制、降低研发成本等多方面赋能人形机器人产业发展。与此同时&#xff0c;特斯拉、波士顿动…

NAND Separate Command Address (SCA) 接口命令解读

CA output packet和CA input packet是Separate Command Address (SCA) NAND接口协议中用于命令和地址传输的关键数据结构。 CA Input Packet: 在SCA接口中&#xff0c;输入到NAND器件的命令和地址信息被组织成并行至串行转换的CA&#xff08;Command and Address&#xff09;输…

linux创建文件并分配权限

linux中对文件的定义 在Linux中&#xff0c;文件是一个具有符号名字的一组相关联元素的有序序列。文件可以包含的内容十分广泛&#xff0c;操作系统和用户都可以将具有一定独立功能的一个程序模块、一组数据或一组文字命名为一个文件。文件名是数据有序序列集合&#xff08;文…

Asp .Net Core 系列: 集成 CORS跨域配置

文章目录 什么是CORS?Asp .Net Core 中如何配置CORS?CorsPolicyBuilder类详解注册以及使用策略三种方式EnableCors 和 DisableCors 特性关于带证书与不带证书代码的实现跨源&#xff08;cross-origin&#xff09;不带请求证书(Credentials)跨源&#xff08;cross-origin&…

【国产之光】开年尝鲜——优秀的AI编码助手 Fitten Code

文章目录 前言1. 工具准备1.0 事先说明1.1 VSCode1.2 Fitten Code1.3 GitHub Copilot 2. 使用测评2.1 需求理解2.2 上下文理解 3. 总结推荐链接 开年尝鲜高质量国产AI编码助手——FittenCode 前言 2024年刚刚开局&#xff0c;清华大学 与 非十科技 就发布了全新的 VSCode AI…

H264码流进行RTP包封装

一.H264基本概念 H.264从框架结构上分为视频编码层&#xff08;VCL&#xff09;和网络抽象层&#xff08;NAL&#xff09;&#xff0c;VCL功能是进行视频编解码&#xff0c;包括运动补偿预测&#xff0c;变换编码和熵编码等功能&#xff1b;NAL用于采用适当的格式对VCL视频数据…

CAN201计网历年大题收集

网络性能计算 e.g1.1 算RTT 传输时间 when you enter the URL in your browser, it initiates an HTTP request. This request is encapsulated in TCP, which is then further encapsulated in IP for routing. The data is transmitted over the physical medium using link …

中国信通院联合发布《数字孪生城市白皮书(2023年)》

2017年“数字孪生城市”概念被首次提出&#xff0c;2021年我国“十四五”规划纲要明确“探索建设数字孪生城市”&#xff0c;2023年《数字中国建设整体布局规划》再次提出“全面提升数字中国建设的整体性、系统性、协同性”以及“探索建设数字孪生城市”等要求。数字孪生城市建…