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

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.hqwc.cn/news/343857.html

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

相关文章

html+css实现子元素完全居中常见方案

详细过程 查看公众号文章 htmlcss实现子元素完全居中常见方案 获取更多内容&#xff0c;请关注微信公众号。搜索“码圈小橙子”&#xff0c;或扫描下方二维码获取关注

Jarvis步进法(Jarvis March)凸包算法

Jarvis步进法&#xff08;也称为包裹法&#xff09;&#xff1a; Jarvis步进法是一种逐步选择凸包顶点的算法。从点集中选择一个起始点&#xff0c;然后在每一步中选择下一个顶点&#xff0c;该顶点是当前点集中与当前点形成的线段上&#xff0c;极角最小的点。该算法的时间复杂…

限流式保护器在户外汽车充装的应用

摘 要&#xff1a;国家标准GB51348-2019中规定储备仓库、电动车充电等场所的末端回路应设置限流式电气防火保护器。电气防火限流式保护器可以有效克服传统断路器、空气开关和监控设备存在的短路电流大、切断短路电流时间长、短路时产生的电弧火花大&#xff0c;以及使用寿命短等…

XSS的利用(包含:蓝莲花、beef-xss)

0x00、环境搭建 dvwa靶场 操作指南和最佳实践:使用 DVWA 了解如何防止网站漏洞_dvwa源代码-CSDN博客 xss漏洞接收平台 下载:GitHub - firesunCN/BlueLotus_XSSReceiver 将解压后的BlueLotus_XSSReceiver原代码放置 phpstudy 安装目录的WWW文件夹下 访问平台:http://127…

【科研技巧】如何判断某个期刊是什么类别及影响因子?是否是顶会?如何期刊内检索?AI写综述?AI做PPT?

相关链接 查找和免费下载文献的方式汇总国内外各大期刊关系、如何查看期刊等级以及查看某篇论文属于哪个期刊登录和访问EI(Engineering Village)数据库查找文献 1 如何判断某个期刊是什么类别及影响因子 https://sci.justscience.cn/ IFold是影响因子 期刊类别为SCIE、查看…

基于springboot+vue心理测试管理系统

摘要 基于Spring Boot 和 Vue 的心理测试管理系统是一个综合利用现代Web开发技术的应用程序。系统采用了Spring Boot作为后端框架&#xff0c;通过其简化的配置和强大的功能提供了稳健的服务器端支持。前端则使用Vue.js&#xff0c;一个灵活、高效的JavaScript框架&#xff0c;…

装机必看:电脑Bios里的CSM兼容模块是啥?打开有啥用?

前言 最近朋友装了一台新的电脑&#xff0c;用的i5-13490f的CPU。但是由于预算有限&#xff0c;手边只有一块GTX650ti&#xff0c;没办法&#xff0c;只好先这么用着了。 谁知道出现了个大问题&#xff1a;电脑开机居然没办法显示。 由于电脑所有的配件基本上都是全新的&…

qt初入门2:qt选择一个文件或者目录,获取当前目录,操作文件目录等整理

最近用qt操作文件或者目录的动作比较多&#xff0c;简单整理一下常用的接口&#xff0c;方便回顾。 总的来说&#xff0c;其实就是用文件选择对话框QFileDialog类&#xff0c;以及操作文件信息的QFileInfo类&#xff0c;以及相关QCoreApplication中静态成员函数获取一些信息&a…

大模型学习与实践笔记(四)

一、大模型开发范式 RAG&#xff08;Retrieval Augmented Generation&#xff09;检索增强生成&#xff0c;即大模型LLM在回答问题或生成文本时&#xff0c;会先从大量的文档中检索出相关信息&#xff0c;然后基于这些检索出的信息进行回答或生成文本&#xff0c;从而可以提高回…

从事铁路工作保护足部,穿什么劳保鞋更安全

铁路运输在我国交通运输业中起着骨干作用&#xff0c;为国民经济的可持续发展和人口流动做出了巨大贡献。安全是铁路运输不可忽视的问题&#xff0c;在作业场地随处能见到“安全就是生命&#xff0c;责任重于泰山”的安全标语&#xff0c;由此可见安全问题是放在首位的。 铁路施…

PHP面试小结(20240108)

PHP 部分 1. php的包管理工具是如何实现自动加载的 换句话问&#xff1a;composer 实现原理是什么&#xff1f;spl_autoload_register() 首先&#xff0c;Composer 是 PHP 的一个包管理和包依赖管理的工具 &#xff0c; 打开安装之后生成的 "vendor" 文件, 里面有个…

使用 EmbeddingBag 和 Embedding 完成词嵌入

&#x1f368; 本文为[&#x1f517;365天深度学习训练营学习记录博客\n&#x1f366; 参考文章&#xff1a;365天深度学习训练营\n&#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制]\n&#x1f680; 文章来源&#xff1a;[K同学的学习圈子](https://www.yuque.co…