C++的allactor
https://zhuanlan.zhihu.com/p/693267319
1 双层内存配置器
SGI设计了两层的配置器,也就是第一级配置器和第二级配置器。同时为了自由选择,STL又规定了 __USE_MALLOC 宏,如果它存在则直接调用第一级配置器,不然则直接调用第二级配置器。SGI未定义该宏,也就是说默认使用第二级配置器。
1.1 一级内存配置器
直接调用malloc和free来配置释放内存,简单明了。
template<int Inst>
class __MallocAllocTemplate //一级空间配置器
{typedef void (*OOM_HANDLER)();
private://these funs below are used for "OOM" situations//OOM = out of memorystatic void* OOM_Malloc(size_t n); //functionstatic void* OOM_Realloc(void *p, size_t newSZ); //functionstatic OOM_HANDLER OOM_Handler; //function pointerpublic:static void* Allocate(size_t n){void* ret = malloc(n);if (ret == NULL)ret = OOM_Malloc(n);return ret;}static void Deallocate(void* p, size_t n){free(p);}static void* Reallocate(void* p, size_t oldSZ, size_t newSZ){void* ret = realloc(p, newSZ);if (ret == NULL)ret = OOM_Realloc(p, newSZ);return ret;}//static void (* set_malloc_handler(void (*f)()))()//参数和返回值都是函数指针void (*)()static OOM_HANDLER SetMallocHandler(OOM_HANDLER f){OOM_HANDLER old = OOM_Handler;OOM_Handler = f;return old;}
};//让函数指针为空
template<int Inst>
void (*__MallocAllocTemplate<Inst>::OOM_Handler)() = NULL;template<int Inst>
void* __MallocAllocTemplate<Inst>::OOM_Malloc(size_t n)
{void* ret = NULL;void(*myHandler)() = NULL;for (;;){myHandler = OOM_Handler;if (myHandler == NULL)throw bad_alloc();(*myHandler)();ret = malloc(n);if (ret != NULL)return ret;}
}template<int Inst>
void* __MallocAllocTemplate<Inst>::OOM_Realloc(void* p, size_t newSZ)
{void* ret = NULL;void(*myHandler)() = NULL;for (;;){myHandler = OOM_Handler;if (myHandler == NULL)throw bad_alloc();(*myHandler)();ret = realloc(p, newSZ);if (ret != NULL)return ret;}
}typedef __MallocAllocTemplate<0> MallocAlloc; //一级空间配置重命名
1.2 二级内存配置器
1.如果用户需要的区块大于128,则直接调用第一级空间配置器
2.如果用户需要的区块大于128,则到自由链表中去找
- 如果自由链表有,则直接去取走
- 不然则需要装填自由链表(Refill)
1.2.1 自由链表

自由链表是一个指针数组,它的数组大小为16,每个数组元素代表所挂的区块大小,比如free _ list[0]代表下面挂的是8bytes的区块,free _ list[1]代表下面挂的是16bytes的区块…….依次类推,直到free _ list[15]代表下面挂的是128bytes的区块
同时我们还有一个被称为内存池地方,以start _ free和 end _ free记录其大小,用于保存未被挂在自由链表的区块,它和自由链表构成了伙伴系统。
1.2.2 工作原理
如果用户需要是一块n字节的区块,且n <= 128(调用第二级配置器),此时Refill填充是这样的:
- 系统会自动将
n字节扩展到8的倍数,再将RoundUP(n)传给Refill。 - 用户需要
n字节,且自由链表中没有,因此系统会向内存池申请nobjs * n大小的内存块,默认nobjs=20 - 如果内存池大于
nobjs * n,那么直接从内存池中取出 - 如果内存池小于
nobjs * n,但是比一块大小n要大,那么此时将内存最大可分配的块数给自由链表,并且更新nobjs为最大分配块数x (x < nobjs) - 如果内存池连一个区块的大小
n都无法提供,那么首先先将内存池残余的零头给挂在自由链表上,然后向系统heap申请空间,申请成功则返回,申请失败则到自己的自由链表中看看还有没有可用区块返回 - 如果连自由链表都没了最后会调用一级配置器。
3 自定义内存配置器
// TODO:为vector写一个内存配置器,当空间大于1000时直接从堆分配内存#include <memory>
#include <vector>
#include <iostream>// 自定义内存配置器
template <typename T>
class CustomAllocator : public std::allocator<T> {
public:// 分配内存T* allocate(std::size_t n) {if (n * sizeof(T) > 1000) {// 大于1000字节时,使用堆分配return static_cast<T*>(::operator new(n * sizeof(T)));} else {// 小于或等于1000字节时,使用默认分配return std::allocator<T>::allocate(n);}}// 释放内存void deallocate(T* p, std::size_t n) {if (n * sizeof(T) > 1000) {// 大于1000字节时,使用堆释放::operator delete(p);} else {// 小于或等于1000字节时,使用默认释放std::allocator<T>::deallocate(p, n);}}
};int main() {// 使用自定义内存配置器的vectorstd::vector<int, CustomAllocator<int>> vec;vec.push_back(1); // 应该使用默认分配方式(通常很小)vec.push_back(2); // 同上vec.resize(1024); // 应该使用堆分配方式(因为1024 * sizeof(int) > 1000)vec.resize(1); // 应该再次使用默认分配方式(因为1 * sizeof(int) <= 1000)return 0;
}
相关文章:
C++的allactor
https://zhuanlan.zhihu.com/p/693267319 1 双层内存配置器 SGI设计了两层的配置器,也就是第一级配置器和第二级配置器。同时为了自由选择,STL又规定了 __USE_MALLOC 宏,如果它存在则直接调用第一级配置器,不然则直接调用第二级配…...
【2025深度学习环境搭建-2】pytorch+Docker+VS Code+DevContainer搭建本地深度学习环境
上一篇文章:【2025深度学习环境搭建-1】在Win11上用WSL2和Docker解锁GPU加速 先启动Docker!对文件内容有疑问,就去问AI 一、用Docker拉取pytorch镜像,启动容器,测试GPU docker pull pytorch/pytorch:2.5.0-cuda12.4…...
在CentOS 7上安装和使用Spleeter音频分离工具的详细步骤
在音频处理领域,Spleeter是一款优秀的开源工具,能够帮助用户轻松实现音频文件中人声和背景音的分离。本文将详细介绍在CentOS 7系统上安装和配置Spleeter的步骤,以及如何使用Spleeter进行音频分离。 准备环境: 在开始安装Spleeter之前&…...
【1】VS Code 新建上位机项目---C#基础语法
VS Code 新建上位机项目---C#基础语法 1 基本概念1.1 准备工具1.2 新建项目2 C#编程基础2.1 命名空间和类2.2 数据类型2.3 控制台输入输出2.3.1 输入输出: write 与 read2.3.2 格式化 : string.Foramt() 与 $2.3.3 赋值与运算2.4 类型转换2.4.1 数值类型之间的转换:(int)2.4…...
电脑经常绿屏(蓝屏)怎么办(解决方法)?
一、排查系统与驱动问题 进入安全模式修复系统 强制重启电脑 3 次触发恢复环境,选择 疑难解答 > 高级选项 > 启动设置 > 重启,按 F5 或 5 进入带网络连接的安全模式3。 在安全模式下,尝试卸载最近安装的软件或更新,尤其…...
clickhouse--本地表和分布式表,副本机制,分片集群
1、本地表和分布式表 ck的表分为两种: 分布式表 一个逻辑上的表,可以理解为数据库中的视图,一般查询都查询分布式表。分布式表引擎会将我们的查询请求路由本地表进行查询,然后进行汇总最终返回给用户。本地表 实际存储数据的表。 …...
react hook useReducer
useReducer useReducer 是 React 中用于状态管理的 Hook,与 useState 不同,它更适合处理复杂的状态逻辑. const [state, dispatch] useReducer(reducer, initialArg, init?) reducer 是一个处理函数,用于更新状态, reducer 里面包含了两个…...
告别阻塞,迎接高效:掌握 AsyncIOScheduler 实现异步任务调度
前言 时间在编程中是宝贵的,直接关联到效率与灵活性,尤其在异步编程里,如何优雅地管理定时任务简直是一门“艺术”。如果你还在用 time.sleep() 来控制延时任务,恐怕你早已体会过它的“痛苦”:程序卡住、线程阻塞、性能急剧下滑。想象一下,你的程序如同一个永远无法按时…...
【基于SprintBoot+Mybatis+Mysql】电脑商城项目之加入购物车和显示购物车列表
🧸安清h:个人主页 🎥个人专栏:【Spring篇】【计算机网络】【Mybatis篇】 🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。 目录 🚀1.加入购物车-数…...
再谈影刀RPA成长学习路线
近期,我将使用影刀RPA开发各电商平台移动端商品信息爬取,实战流程会在QQ群里分享,欢迎大家进群,一起探讨交流! 1. 影刀RPA学习路线概述 1.1 学习目标与意义 学习影刀RPA的目标在于掌握一种高效的工作自动化工具,以提…...
PHP-综合4
[题目信息]: 题目名称题目难度PHP-综合42 [题目考点]: PHP综合训练[Flag格式]: SangFor{Ouk3i63BuShgxqdRcn_9kMNqKFDe5j4f}[环境部署]: docker-compose.yml文件或者docker tar原始文件。 http://分配ip:2087[题目writeup]:…...
学习笔记-沁恒第五讲-米醋
一,设置音量 上次 这次 #include "uart.h" #include "debug.h" void audio_init() { Usart3_Init(); } void audio_play(u8 num) { u8 string[]{0x7e,0x05,0x41,0x00,num,0x05^0x41^0x00^num,0xef}; u8 i; for(i0;i<7;i) { USART_Se…...
【JavaScript】JavaScript 常见概念 - 变量与数据类型 - 运算符 - 条件语句 - 循环 - 函数 - 数组操作 - 对象
1. 变量与数据类型 变量声明 JavaScript 提供了三种方式来声明变量: var(全局或函数作用域,不推荐)let(块级作用域,推荐)const(常量,块级作用域,推荐&…...
Web自动化之Selenium添加网站Cookies实现免登录
在使用Selenium进行Web自动化时,添加网站Cookies是实现免登录的一种高效方法。通过模拟浏览器行为,我们可以将已登录状态的Cookies存储起来,并在下次自动化测试或爬虫任务中直接加载这些Cookies,从而跳过登录步骤。 Cookies简介 …...
AI手机的技术细节
前序:先说各个功能涉及到的技术,再说宏观系统架构。AI手机有这样几个做法,给手机侧边增加一个按键;把手机的语音助手做的很好,能够快速稳定的进行唤醒;通过特殊形式的触摸手机的曲面屏位置等来进行唤醒AI …...
10. 九转金丹炼矩阵 - 矩阵置零(标记优化)
哪吒在数据修仙界中继续他的修炼之旅。这一次,他来到了一片神秘的金丹谷,谷中有一座巨大的九转金丹炉,炉身闪烁着神秘的光芒。金丹炉的入口处有一块巨大的石碑,上面刻着一行文字:“欲破此炉,需以九转金丹之力,炼矩阵之零,标记优化定乾坤。” 哪吒定睛一看,石碑上还有…...
[实现Rpc] 客户端 | Requestor | RpcCaller的设计实现
目录 Requestor类的实现 框架 完善 onResponse处理回复 完整代码 RpcCaller类的实现 1. 同步调用 call 2. 异步调用 call 3. 回调调用 call Requestor类的实现 (1)主要功能: 客户端发送请求的功能,进行请求描述对服务器…...
Java 大视界 -- 深度洞察 Java 大数据安全多方计算的前沿趋势与应用革新(52)
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...
山东大学软件学院nosql实验三
实验题目: 用Java做简单查询(2学时) 实验内容 用API方式,做简单查询。 实验要求 在以下要求中选择至少2个,使用Java语言实现数据查询,最终把数据输出到前端界面。 (1)找出年龄小于20岁的所有学生 &…...
正态分布的奇妙性质:为什么奇数阶中心矩(odd central moments)为零?
正态分布的奇妙性质:为什么奇数阶矩为零? 正态分布(Normal Distribution)是统计学中最常见的分布之一,它的钟形曲线几乎无处不在,从身高体重到测量误差,都能看到它的影子。除了均值和方差这两个…...
TypeScript的装饰器元数据反射:实现依赖注入容器
TypeScript的装饰器元数据反射:实现依赖注入容器 在现代前端与后端开发中,依赖注入(Dependency Injection, DI)是一种重要的设计模式,它能够解耦组件之间的依赖关系,提升代码的可维护性和可测试性。TypeSc…...
毕业不焦虑,百考通AI帮你高效搞定本科毕业论文
深夜的电脑屏幕前,一个大学生正对着空白的文档发呆,毕业论文的截止日期日益临近,他却连选题都还没确定。这或许是无数毕业生共同经历过的煎熬时刻。 一、毕业季的论文困境:每个本科生都懂 又到一年毕业季,校园里弥漫着…...
Java八股之JDK1.8 的新特性
JDK1.8 的新特性以下是除去 CompletableFuture、重复注解和接口默认方法之外的 JDK 1.8 的新特性,并附上一些参考代码案例:1. Lambda 表达式Lambda 允许在 Java 中更简洁地使用函数式编程风格。它提供了一种简洁的方式来表示匿名函数,并使代码…...
C++ STL 标准模板库 六大核心
文章目录容器(Containers)—— 存放数据算法(Algorithms)—— 操作数据迭代器(Iterators)—— 容器与算法的桥梁仿函数 / 函数对象(Functors)适配器(Adapters)…...
Go 中嵌入类型字段在派生结构体字面量中的初始化规则详解
Go 语言中,嵌入类型(embedded type)的字段虽可被派生结构体直接访问,但不能作为字段名出现在结构体字面量中;必须通过显式初始化嵌入类型本身,或先创建实例再赋值。 go 语言中,嵌入类型&am…...
WooCommerce 用户登录状态控制元素显隐的 CSS 实现方案
本文详解如何在 woocommerce 中通过 css 精准控制元素(如价格)在用户登录/登出时的显示与隐藏,重点解决常见失效问题,并提供可维护、无需 php 输出样式的纯 css 方案。 本文详解如何在 woocommerce 中通过 css 精准控制元素&…...
iVX实战:手把手教你用零代码搭建一个企业内部OA系统(含表单和流程)
iVX实战:零代码构建企业OA系统的完整指南 当创业团队扩张到20人以上时,行政主管小张发现纸质审批流程已经严重拖累效率——报销单在部门间传递经常丢失,请假记录难以追踪统计。传统软件开发动辄数十万的报价和三个月起步的开发周期࿰…...
手把手教你理解交叉编译:从嵌入式开发到Rust编译Android So库
手把手教你理解交叉编译:从嵌入式开发到Rust编译Android So库 当你在x86架构的笔记本上按下编译按钮,却要为树莓派(ARM架构)生成可执行文件时,背后发生了什么?这种"在A平台编译B平台程序"的技术&…...
DELL SCv3020风扇狂转别慌!手把手教你排查‘脑裂’与控制器升级(附串口连接避坑指南)
DELL SCv3020风扇异常诊断全攻略:从脑裂检测到固件升级实战 机房里突然响起的风扇轰鸣声往往让运维人员心头一紧——特别是当这台设备是承载关键业务的DELL SCv3020存储系统时。上周我就经历了这样一场惊心动魄的排障:原本只在周末偶尔出现的风扇狂转现…...
Frenet与Cartesian坐标系互转实战:Python函数库封装与性能优化
1. 为什么需要Frenet与Cartesian坐标系互转 在自动驾驶和机器人路径规划领域,我们经常需要在两种坐标系之间进行转换:Cartesian坐标系(直角坐标系)和Frenet坐标系。Cartesian坐标系就是我们熟悉的x、y、z三维空间坐标,…...
