C++内存管理(候捷)第二讲 笔记

侯捷C++八部曲笔记(一、面向对象) 阅读详情

VC6 malloc

在这里插入图片描述
cookie一定占用8个字节。上下各4个字节
Cookie 是一小段额外的标识信息,用于在边界检查中检测缓冲区溢出。它通常是一个特殊的值,放置在分配的内存块的开始位置。记录内存分配出去的大小
Debug Header 包含一些调试信息,例如分配的文件名、行号等。这些信息用于调试和跟踪内存分配的源
block size 分配的实际数据块
Debug Tail 包含与调试信息相关的尾部数据
pad 对齐填充

VC6标准分配器之实现

在这里插入图片描述
VC6标准分配器里面的allocate和deallocate的实现只是调用::operator new 和::operator delete, 没有任何特殊设计。底层是malloc和free

BC5标准分配器之实现

在这里插入图片描述
Borland5 编译器只是调用::operator new 和::operator delete, 没有任何特殊设计

G2 9标准分配器之实现

在这里插入图片描述
allocate和deallocate的实现也是调用::operator new 和::operator delete, 没有任何特殊设计
在这里插入图片描述
GNU C++2.9容器使用的分配器,不是std::allocator,而是std::alloc

G2.9 std::alloc VS G4.9 __pull_alloc

G2.9 std::alloc在G4.9中是 __pull_alloc

G4.9 __pull_alloc用例

G4.9版本中标准分配器std::allocator的实现,里面的allocate和deallocate的实现只是调用::operator new 和::operator delete, 没有任何特殊设计
在这里插入图片描述
__pull_alloc去除了cookie(一个元素带有上下两个cookie,共8B)。上图每个double相距8字节,下面的double相距10字节

G2.9 std::alloc

在这里插入图片描述
前文的Per class allocator每个类重载了operatpr new和operator delete。每个类单独维护一个链表

为了通用的将operator new的分配操作提取到alloc类。为了适应不同类的大小,std::alloc为所有的类维护16个链表,每个链表负责不同大小的区块分配,从小到大分别负责8B, 16B, 24B, 32B,…, 按8的倍数增长,最大是16 x 8 = 128B。当大小不为8的倍数的时候,分配器会自动将其对齐到8的倍数。当大小超过128B时,就交给malloc来单独处理。

当一个vector里面存了一个“stone”类型的对象,它的大小是32B,那么就会启用下面的#3的链表,它负责32B区块的分配。每次分一大块(里面有20个小块,每个都是32B,但是实际分配的时候是20个小块的两倍大小,剩余的部分暂且不用), 指定一个小块给stone即可
在这里插入图片描述
嵌入式指针:借用A对象所占用的内存空间中的前4个字节,这4个字节用来 链住这些空闲的内存块;
一旦某一块被分配出去,那么这个块的 前4个字节 就不再需要,此时这4个字节可以被正常使用
使用的时候看成对象实例,空闲的时候会看成next指针

G2.9 std::alloc运行一瞥

在这里插入图片描述
分配器的客户是给容器用的,不是给用户用的。如果直接用分配器,要记住分配了多大,因为没有cookie。再回收时告知分配器。容器所有的元素大小都一样,第一个模版参数是类型,直接sizeof可以得到大小
在这里插入图片描述
刚开始的时候pool为空,要分配32 * 20 *2 + RoundUp(0 >> 4)= 1280B大小的空间为pool,然后从pool里面切割20个小块(共640B)挂在#3链表上,剩下的640B放在pool里面备用
在这里插入图片描述
创建了新的容器,元素大小为64B,此时链表为空。由于上页的pool里面还剩640B,现在将其切分为640/64 = 10个区块,第一个给容器,剩下的9个挂在list #7. 此时pool的大小为0,因为被切分挂到链表上了
在这里插入图片描述
在上面的基础,新建容器,元素大小为96B,先检查pool是否有余量,由于pool为空,此时调用malloc分配一大块作为pool,总共大小为96x 20 x 2 + RoundUp(1280 >> 4) = 3840 + 80 = 3920B,其中20个区块拿出来用,1个区块返回给容器,另外19个区块挂在#11链表上,剩下的就是pool的容量,即3920−(96×20)=3920−1920=2000 B
在这里插入图片描述
新建容器,元素大小是88B,pool中的余量为2000,将2000切分为20个区块(每个区块88B),第一个区块给容器,剩下的19个区块挂在#10链表上。pool剩下的余量:2000 - 88 x 20 = 240B
在这里插入图片描述
容器连续申请3次88B大小的空间,由于已经在#10 链表上挂了19个大小为88B的区块,直接从该链表上拿下来3个区块返回给容器即可。pool大小还是240
在这里插入图片描述
新的容器,元素大小为8B,pool容量为240,从pool里面切分出20个区块,共8B x 20 = 160B大小,第一个返回给容器,其余19个区块挂在#0链表上pool剩240 - 160 = 80B
在这里插入图片描述
新的容器,元素大小为104B。pool余量为80B,此时这个80B大小的空间就是碎片,需要将其挂在某一个链表上。挂在80 / 8 - 1 = 9号链表。碎片处理完之后,再处理现在的需求104B的分配。
现在再调用malloc分配一大块,大小为104 x 20 x 2 + RoundUp(5200 >> 4) = 4160 + RoundUp(325) = 4160 + 328 = 4488,pool容量为4488 - 104 x 20 = 2408B,把第一个区块分配给容器,切出的19个挂在#12 list上。pool的余量为2408B。累计申请量为5200 + 4488 = 9688B
在这里插入图片描述
请112B,pool容量为2408,从里面取出112 * 20 = 2240,第一个区块返回给容器,留下19个区块挂在13号链表上。pool余量为2408 - 2240 = 168B。
在这里插入图片描述
申请48B,5号链表,pool余量168B。分配168 / 48 = 3个大小为48的区块,pool余量为24B
在这里插入图片描述
实验过程中把系统heap大小设置为10000,前面已经累计分配了9688B,因此无法满足本次内存分配
alloc从手中资源取最接近72B的大小回填pool,这里最接近的是80B(9号链表有1个空的可用),然后从80B中切72B给容器,pool剩下80 - 72 = 8B。
9号链表指针指向0
在这里插入图片描述
再申请72B,list #8没有区块可用,pool余量为8,先将pool余额挂在list #0。然后想要调用malloc分配72 x 20 x 2 + RoundUP(9688 >> 4) = 3488B的空间,无法满足分配
于是alloc从手中资源取最接近72B的88B(list #10)回填pool,因为上面的80B(list #9)已经用完了,从88B中切出72B返回给容器,pool余额:88 - 72 = 16B。
在这里插入图片描述
新的容器申请120B,挂在120 / 8 - 1 = 14号链表。pool不足。将上面的16B挂在1号链表上。
alloc从手中资源中取最接近120B的区块回填pool,但是14号链表和15号链表都是空的,于是无法分配。
在这里插入图片描述

G2.9 std::alloc源码剖析

分为两级分配器,分别是第一级分配器和第二级分配器。
第一级分配器不重要,主要模拟new handler的作用,处理一下内存分配的情况。
GC4.9不再有一级
在这里插入图片描述
常量:ALIGN 对齐量, MAX_BYTES元素块最大可分配量,以及NFREELISTS链表个数/数组长度

size_t ROUND_UP(size_t bytes) {
    return (((bytes) + __ALIGN-1) & ~(__ALIGN - 1));
}

ROUND_UP是将分配的大小变成8的倍数,计算分配追加量
union_obj嵌入式指针,原本是两个成员,其中一个用不到(方便理解),因此改为struct

size_t FREELIST_INDEX(size_t bytes) {
    return (((bytes) + __ALIGN-1)/__ALIGN - 1);
}

FREELIST_INDEX根据bytes大小,指定到是哪个链表

char*   start_free = 0; // 指向战备池pool的头
char*   end_free = 0;   // 指向战备池pool的尾
size_t  heap_size = 0;  // 累计分配大小

在这里插入图片描述
volatile和多线程相关
my_free_list指向链表指针数组的指针
当n大小大于最大分配量,另外处理,直接malloc
refill(ROUND_UP(n)),链表充值,从pool中去拿区块。上述一览的过程

链表很长,大量分配,大量回收后,无法判断哪些是连续的,一定要连续的内存块才可以free,所以deallocate没有free,这个不算内存泄露
在这里插入图片描述
在这里插入图片描述
refill默认一次抓20,只是初值
调用chunk_alloc函数来挖一大块内存
当分配的区块为1时,就直接交给客户(容器)
chunk指的是一大块,然后将其切割,建立free list。refill的参数n表示一小个区块的大小
切割for循环从1开始,因为第一块内存要直接给出去
指针转为字节跳转后再转回obj*
在这里插入图片描述
pool空间满足20个区块的需求
pool空间只能满足1到19个区块的需求
pool不能满足1块
在这里插入图片描述
往更大内存链表挖内存时,只用一块来判断,因为无法确定链表里的内存是否连续
在这里插入图片描述
定义一些初始数据

G2.9 std::alloc观念大整理

在这里插入图片描述
容器c使用alloc分配空间,看16条链表中哪一条可以提供区块,分配给它,不带cookie
new出来的对象Foo(2),带有cookie,通过调用底层malloc,push_back的时候不带cookie
在这里插入图片描述
比较判断的时候把具体的值写在前面,防止出现将==写成=赋值的情况

c++标准程序库《附源码》(侯杰) STL,C++三大编程技术之一(面向对象编程;泛型编程,即STL;com编程)。凡是学C++如不知道STL,那你的C++之路还有很长。侯杰翻译的这本书,能够让你熟练的掌握STL的用法。 立即下载

相关推荐

C++标准库(The C++ Standard Library)中文版侯杰 译

The C++ Standard Library(中文版)侯杰 译 c++标准库,STL方面的圣经,里面提供了容器和高效算法,相当使用,如果你是c++资深程序员,不会用STL是不可想象的,所以吐血推荐!!!

侯杰-C++面向对象高级编程-笔记

学习侯杰(C++面向对象高级编程)做的一些笔记,根据视频顺序进行章节划分,可参考相关内容进行学习,需要一定的C++基础。

HEr_520的博客 1616

深入浅出 侯杰

深入浅出 侯杰,MFC最好的评述,包括他的著作《深入浅出MFC》书中的源代码,学习MFC的好帮手。

侯杰(面向对象上01)面向对象简介

继承(inheritance)&学习Class之间的关系。注释:本章需要重点掌握的是面向对象的定义以及基于对象的定义。&知道一个程序需要编译、连结才能被执行。&以良好的方式编写C++ class。_复合(composition)&目标:培养正规的、大气的编程习惯。_委托(delegation)一般都用C++98 C++11。@变量(variables)(如何建立一个可运行程序)@作用域(scope)&知道如何编译和链接。

weixin_37386610的博客 593

深入浅出MFC(侯杰)

深入浅出MFC(侯杰)

侯杰的深入浅出MFC

非常经典的书籍,学习VC的人必备案头书籍

C++ 侯捷 内存管理

C++ 侯捷 内存管理

zaizai1007的博客 1239

N5105 PVE UEFI核显直通Windows:从黑屏到HDMI输出的实战调优

本文详细介绍了在N5105处理器上实现PVE UEFI核显直通Windows的实战调优方法。针对黑屏和HDMI音频无法识别等常见问题,提供了系统参数调整、驱动模块加载、虚拟机配置等解决方案,帮助用户成功实现核显直通并优化性能。

weixin_42566424的博客 204

C++ STL之container

C++ STL之Container,参考视频《STL源码剖析》

A805012145的博客 548

stc8g1k08硬件iic读取aht20温湿度及0.91寸oled显示

使用stc8g1k08读取aht20温湿度及0.91寸oled显示。

qq_61688416的博客 2771

暗黑破坏神2重制版 mod制作教程(一)

暗黑2重制版mod修改教程

hhhh2312的博客 7455

C++内存管理(候捷)第一讲 笔记

候捷内存管理学习笔记

Mhypnos的博客 1104

Windows11开机必看:3种方法跳过联网激活(含最新OOBE命令)

本文详细介绍了Windows11新机开箱时绕过联网激活的三种实用方法,包括任务管理器终止进程法、命令行强制终止法和最新的OOBE\BYPASSNRO命令法。特别推荐使用微软官方预留的OOBE命令,操作简单且无副作用,帮助用户快速完成系统设置。

weixin_28366353的博客 1627

C++内存管理(候捷)第三讲 笔记

候捷内存管理学习笔记

Mhypnos的博客 1384

差分音频转单端音频单电源方案

其中,芯片设计中的轨到轨输出(Rail-to-Rail Output) 是指通过特定的电路设计,使芯片(如运算放大器、驱动电路等)的输出电压能够达到或接近电源电压的上下极限(即“电源轨”),从而最大化信号的动态范围。最终,Vout=R2/R1*(Vin2−Vin1),即输出电压为输入电压差(Vin2−Vin1)乘以电阻比R2/R1。2、电阻:R1、R2、R3、R4是电路中的电阻,其中R1 = R3,R2 = R4。因R1=R3,R2=R4,且Vn=Vp,设R1=R3=R,R2=R4=kR。

电子绿洲的博客 4959

【06】C#入门到精通——C# 多个 .cs文件项目 同一项目下添加多个 .cs文件

本文介绍了如何将C#游戏开发中的代码从单个.cs文件拆分到多个.cs文件中,以提升代码的可维护性和可读性。文章演示了在Visual Studio中创建Hero类和ShowInfo类的具体步骤:通过右键项目名添加新建类,将原有代码分别剪切到对应的类文件中,并自动生成命名空间。拆分后需要在Program.cs中通过"using"指令引用这些类,最后通过运行测试验证功能正常。这种模块化代码组织方式能有效解决单一文件代码过长、结构混乱的问题。

程序员,他们想的是什么?他们想的永远都是技术,他们崇尚的也永远都是技术。 1137

候捷C++内存管理学习笔记

这里使用new char分配一块未初始化的原始内存空间,因为char是C++中最小的地址单位,占用的大小是1字节,相较于直接new Screen[screenChunk]避免了构造函数的调用,因为我们要管理的是原始的内存空间,而且使用char得到的内存会自动对齐,满足Screen的对齐要求。对i取地址然后转换为char*类型的指针,步长为1字节(int*型指针步长为4字节),这时候就可以通过*(char*)&i解引用获取i中存储的第一个字节的值,如果是大端,存储的值应该是0,如果是小端,存储的值应该是1。

z2251226240z的博客 711

yolov5改进之Fasternet主干网络替换

fasternet替换yolov5主干网络

qq_41920323的博客 5144

C++内存管理(候捷)第五讲 笔记

候捷内存管理学习笔记

Mhypnos的博客 1143

【光伏风电功率预测】偏差考核每月少几十万:STL-VMD + Informer-LSTM 在某基地的落地案例

摘要:某风光一体化基地通过STL-VMD二次分解与Informer-LSTM并行残差模型,在不推翻现有预测系统的情况下,将风光功率预测的综合nRMSE降低了1.2-1.5个百分点。该方案通过分解预测误差为多个子序列,并采用不同模型处理各频段特征,显著改善了关键时段的预测精度。实施后,风电nRMSE从9.0%降至7.6%,光伏从10.2%降至8.8%,每月减少偏差考核费用30-50万元。项目经验表明,数据质量优化、参数调优及与业务目标对齐是关键成功因素,该技术路线具有可复制性,为风光基地预测精度提升提供了有效

专注AI大模型,软件混淆,授权 265

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

C++内存管理(候捷)第四讲 笔记

候捷内存管理学习笔记

Mhypnos的博客 1194

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C++内存管理机制笔记2

GNU C++2.9版本alloc分配器的具体实现与源码剖析

阿正的梦工坊 1677

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

C++ 基础 候捷老师(上)笔记

注意:这是 bilibili 上侯捷老师的 C++ 基础 上 部分,自己做的笔记,以供复习。 侯捷老师 C++ 视频 **cpp 学习笔记** 01 基础知识点 1.1 学习目地 培养正规的、大气的编程习惯 以良好的方式编写 C++ class  Object Based (基于对象) 没有指针的类 带指针的类 学习 class 之间的关系     Object Orient...

田罗文 982

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

Loki库中allocator的设计代码,以及对GNU C++4.9版本中其他allocator的介绍,主要包含bitmap_allocator

阿正的梦工坊 1431

候捷C++学习笔记(上)

浅拷贝:对于指针对象来说浅拷贝是非常危险的,如果简单的把a赋值给b(b = a),那么b指针原来所指向内存位置的内容就丢失了,b指针指向了a指针所指向的位置,造成了内存泄漏,而且还形成了两个指针指向同一个位置的局面(相当于b是a的别名,应该尽量避免别名的出现)。作用域是定义它的类,只能通过类名::来访问。一般情况下都可以使用引用传递,除非返回的对象的作用域是local的,即在函数中创建的临时对象,该对象在函数调用结束后就会被销毁,这时外部接收到的引用是损坏的,所以在这种情况下不可以使用引用传递。

z2251226240z的博客 1096

c++--候捷视频学习(三)堆、栈与内存管理

ctor:构造函数 上图中,函数结束时c1占用的栈的内存自动释放,但是p占用的堆的内存要手动释放。 堆的生命周期就在函数内,结束的时候析构函数被调用(说明析构函数是用来清理的) new可以分解为三个动作:开内存;转型;调用构造函数。 deleta可以分解为两个动作:调用析构函数;释放内存。 内存管理 例如:在vc编译器瞎,debug模式下动态new一个complex类型的内存,实际开辟多大的,如图第一列。数据是8个字节;前边带8个灰色框,后边带一个灰色框,每个灰色框是4个字节;最后再带两个红

weixin_41012399的博客 760
上一篇: C++内存管理(候捷)第一讲 笔记
下一篇: C++内存管理(候捷)第三讲 笔记
Mhypnos
博客等级 码龄12年 731粉丝 123原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值