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.mzph.cn/news/626251.shtml

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

相关文章

XSS漏洞:xss-labs靶场通关

xss系列往期文章&#xff1a; 初识XSS漏洞-CSDN博客 利用XSS漏洞打cookie-CSDN博客 目录 第一关 第二关 第三关 第四关 第五关 第六关 第七关 第八关 第九关 第十关 第十一关 第十二关 第十三关 第十四关 第十五关 第十六关 第十七关 第十八关 第十九关 …

Unity | AudioSource 无声音

Unity | AudioSource 无声音 你是否也会遇到相同的问题&#xff1f;AudioSource没声音&#xff1f; 解决&#xff1a; 注意查看一下几处声音设置&#xff1a;

XS2180四通道,兼容 IEEE 802.3at/af以太网供电 PSE 控制器 V1.0

XS2180 是一个四通道、供电设备&#xff08; PSE &#xff09;电源控制 器&#xff0c;设计用于 IEEE 802.3at/af 兼容 PSE 。器件提供用 电设备&#xff08; PD &#xff09;检测、分级、限流以及负载断开检测。器 件支持自动工作和软件编程。器件还支持最新二事件分…

宁夏银行关键系统基于OceanBase的创新实践

宁夏银行成立于 1998 年&#xff0c;是宁夏第一家“宁”字号地方商业银行&#xff0c;西部地区第一家以省级行政区命名的地方商业银行。2016 年&#xff0c;被中国人民银行评为宁夏地区系统性重要银行。目前&#xff0c;全行设分支机构 97 家&#xff0c;其中总行营业部 1 家&a…

centos7 arm服务器编译安装PaddlePaddle

前言 随着国产服务器发展&#xff0c;部署项目需要用在国产服务器上&#xff0c;官方教程里面很多没有讲解到&#xff0c;安装过程中出现了各种各样的问题&#xff0c;以下是对官方教程的补充&#xff0c;有什么问题&#xff0c;欢迎指正&#xff01; 一、环境准备 gcc: 8.2版…

BootStrap 实现轮播图

Bootstrap中文网 1、下载BootStrap 2、引入相关文件 在下载好的文件夹中找到下面的文件&#xff0c;复制到自己的项目中并引入 <link rel"stylesheet" href"bootstrap/css/bootstrap.min.css" /><script src"bootstrap/js/jquery.min.js…

【数据结构与算法】之数组系列-20240116

这里写目录标题 一、15. 三数之和二、16. 最接近的三数之和三、49. 字母异位词分组四、53. 最大子数组和五、189. 轮转数组六、179. 最大数 一、15. 三数之和 提示 中等 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k…

【教3妹学编程-算法题】3006. 找出数组中的美丽下标 I

3妹&#xff1a;呜呜&#xff0c;烦死了&#xff0c; 脸上长了一个痘 2哥 : 不要在意这些细节嘛&#xff0c;不用管它&#xff0c;过两天自然不就好了。 3妹&#xff1a;切&#xff0c;你不懂&#xff0c;影响这两天的心情哇。 2哥 : 我看你是不急着找工作了啊&#xff0c; 工作…

如何使用服务器?

文章目录 如何使用服务器&#xff1f;一、工具二、第一种方法三、第二种方法四、实例 个人经验 如何使用服务器&#xff1f; 本文详细介绍了如何利用服务器跑模型&#xff0c;具体流程如下&#xff1a; 一、工具 ToDeskPyCharm Professional移动硬盘JetBrains GatewayGit 二…

dp--62. 不同路径/medium 理解度A

62. 不同路径 1、题目2、题目分析3、复杂度最优解代码示例4、抽象与扩展 1、题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中…

免费的域名要不要?

前言 eu.org的免费域名相比于其他免费域名注册服务&#xff0c;eu.org的域名后缀更加独特。同时&#xff0c;eu.org的域名注册也比较简单&#xff0c;只需要填写一些基本信息&#xff0c;就可以获得自己的免费域名。 博客地址 免费的域名要不要&#xff1f;-雪饼前言 eu.org…

Sqoop安全性:确保安全的数据传输

确保数据传输的安全性在大数据处理中至关重要。Sqoop作为一个用于数据传输的工具&#xff0c;也提供了多种安全性措施&#xff0c;以确保数据在传输过程中的机密性和完整性。本文将深入探讨Sqoop的安全性特性&#xff0c;提供详细的示例代码和全面的内容&#xff0c;以帮助大家…

读元宇宙改变一切笔记09_硬件与互操作性(下)

1. 移动互联网的继承者 1.1. 要想让元宇宙成为现实&#xff0c;需要开发新的标准&#xff0c;创建新的基础设施&#xff0c;可能还需要对长期存在的TCP/IP协议进行彻底改革 1.1.1. 采用新的设备和硬件&#xff0c;甚至可能打破技术巨头、独立开发者和终端用户之间的权利平衡 …

CDMP认证与CDGA/CDGP的区别有哪些?

&#x1f451;CDMP是DAMA国际组织的全英文考试 &#x1f308;CDGA和CDGP是DAMA中国主导&#xff0c;考试为中文考试。需要在规定的时间内报名后&#xff0c;参加线下笔试考试。 &#x1f44d;CDGA、CDGP证书和英文版的CDMP证书都是国际通用的&#xff0c;是数据管理领域专业的职…

js等于操作符和全等操作符(== 和 ===)的区别,在什么情况下使用

在JavaScript中&#xff0c;&#xff08;等于操作符&#xff09;和&#xff08;全等操作符&#xff09;都是用来比较两个值是否相等的工具&#xff0c;但它们有一些重要的区别。 会尝试进行类型转换&#xff0c;然后再比较。这意味着它可能会将不同类型的值转换为相同类型&…

【教3妹学编程-算法题】3008. 找出数组中的美丽下标 II

3妹&#xff1a;呜呜&#xff0c;烦死了&#xff0c; 脸上长了一个痘 2哥 : 不要在意这些细节嘛&#xff0c;不用管它&#xff0c;过两天自然不就好了。 3妹&#xff1a;切&#xff0c;你不懂&#xff0c;影响这两天的心情哇。 2哥 : 我看你是不急着找工作了啊&#xff0c; 工作…

爬虫-8-数据存储-mysql

#mysql占空间最小吧&#xff0c;数据存储没问题吧 (//∇//)

【.net core】yisha框架,bootstrap-table组件增加固定列功能

需要引入 bootstrap-table-fixed-columns.css和bootstrap-table-fixed-columns.js文件 文件代码&#xff1a; bootstrap-table-fixed-columns.css样式文件代码 .fixed-table-header-columns, .fixed-table-body-columns {position: absolute;background-color: #fff;displa…

C++系统笔记教程----vscode远程连接ssh

C系统笔记教程 文章目录 C系统笔记教程前言开发环境配置总结 前言 开发环境配置 Ubuntu20.24VScode 如果没有linux系统&#xff0c;但是想用其编译&#xff0c;可以使用ssh远程连接。 首先进入vscode,打开远程连接窗口&#xff08;蓝色的小箭头这&#xff09; 选择连接到主机…

FFmpeg之AVFormat

文章目录 一、概述二、解封装流程三、重要结构体3.1、AVFormatContext3.2、AVInputFormat3.3、AVOutputFormat3.4、AVStream 四、重要函数分析4.1、avformat_alloc_context4.2、avformat_open_input4.2.1、init_input4.2.2、av_probe_input_format2 4.3、avformat_find_stream_…