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 memory
    static void* OOM_Malloc(size_t n); //function
    static void* OOM_Realloc(void *p, size_t newSZ); //function
    static OOM_HANDLER OOM_Handler; //function pointer

public:
    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 _ freeend _ 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() {
    // 使用自定义内存配置器的vector
    std::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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DeepSeek R1/V3满血版——在线体验与API调用

前言&#xff1a;在人工智能的大模型发展进程中&#xff0c;每一次新模型的亮相都宛如一颗投入湖面的石子&#xff0c;激起层层波澜。如今&#xff0c;DeepSeek R1/V3 满血版强势登场&#xff0c;为大模型应用领域带来了全新的活力与变革。 本文不但介绍在线体验 DeepSeek R1/…

forge-1.21.x模组开发(二)给物品添加功能

功能效果 创建一个兑换券&#xff0c;当使用兑换券对着兑换机右键时&#xff0c;获得一条烤鱼 创建兑换券 创建ExchangeCouponsItem.java&#xff0c;继承Item&#xff0c;定义兑换券内容 public class ExchangeCouponsItem extends Item {public ExchangeCouponsItem(Prop…

NIO-Reactor模型梳理与demo实现

关于NIO&#xff0c;我们在上一篇 linux下网络编程socket&select&epoll的底层实现原理 就介绍了网络阻塞IO、以及基于事件驱动的非阻塞IO。对于NIO的API基本使用是java提供的接口&#xff0c;然后我们在业务上对NIO的使用&#xff0c;也是有不同的使用方法的。然后在我…

数据结构与算法-搜索-双向搜索 和 A*算法(字串变换,八数码,第k短路)

双向搜索&#xff1a; 双向搜索是一种优化的搜索策略&#xff0c;常用于在状态空间中寻找从起始点到目标点的路径或满足特定条件的状态 基本概念 双向搜索指的是从起始点和目标点同时出发进行搜索的方法。传统的单向搜索&#xff0c;如深度优先搜索&#xff08;DFS&#xff09…

Java实现斗地主-做牌以及对牌排序

卡牌类 public class Card {private String size;//大小private String color;//花色private int value;//权值public Card() {}public Card(String size, String color, int value) {this.size size;this.color color;this.value value;}public String toString(){return …

Tesla T4 显卡 Linux 64-bit Ubuntu 24.04 驱动和cuda系统支持版本

搜索结果 | <dd~ProductName> | <dd~OSName> | NVIDIA 操作系统和硬件平台&#xff1a;页面展示的是适用于Linux 64位操作系统&#xff0c;版本为Ubuntu 24.04&#xff0c;并且专门为Tesla T4等NVIDIA数据中心GPU提供驱动程序。 驱动版本&#xff1a;页面列出了不…

申请SSL证书,如何完成域名验证

一、前言 给大家分享一下Lets Encrypt 证书申请时&#xff0c;如何完成域名验证这一步操作的方法。 二、为什么要进行域名验证 申请SSL证书时进行域名验证的主要原因是确保证书只颁发给有权控制特定域名的实体。这是为了保证互联网的安全性和信任&#xff0c;防止恶意方获取不…

Innovus中快速获取timing path逻辑深度的golden脚本

在实际项目中我们经常会遇到一条timing path级数特别多&#xff0c;可能是一两页都翻不完。此时&#xff0c;我们大都需要手工去数这条path上到底有哪些是设计本身的逻辑&#xff0c;哪些是PR工具插入的buffer和inverter。 数字IC后端手把手培训教程 | Clock Gating相关clock …

MySQL | MySQL库、表的基本操作01

MySQL库、表的基本操作01 一、库操作1.1 查看数据库1.2 创建数据库1.3 选择数据库1.4 查看创建数据库的SQL语句1.5 修改数据库1.6 删除数据库 二、表操作2.1 创建数据表2.2 查看表2.3 查看表结构2.4 查看创建数据库的SQL语句2.5 修改表2.6 删除表 ⚠️MySQL版本 8.0 一、库操作…

Cocos Creator Shader入门实战(一):材质和Effect的了解

引擎版本&#xff1a;3.8.5 环境&#xff1a; Windows 简介 在Cocos Creator中&#xff0c;游戏炫彩缤纷的效果是借助着色器(Shader)来实现的。 Cocos主要基于OpenGL ES&#xff0c;而Shader的编写则是在可编程渲染管线中基于修改&#xff1a;顶点着色器(Vertex) 和 片段着色…

【2025深度学习环境搭建-1】在Win11上用WSL2和Docker解锁GPU加速

建议有&#xff1a; 较新的win11电脑&#xff0c;GPU是nvidia一点点Linux基础一点点Docker基础 一、安装WSL2 【控制面板】》【程序】》【启用或关闭Windows功能】 打开三个功能&#xff1a;【Hyper-V】【Virtual Machine Platform】【适用于Linux的Windows子系统】 可能看…

每天五分钟深度学习pytorch:使用Inception模块搭建GoogLeNet模型

本文重点 前面我们学习了Incetption模块,它的作用类似于vgg块对于VGG网络模型一样,本文我们使用Inception搭建GoogLeNet网络,如果使用卷积层开始从头开始搭建GoogleNet,那么这样看起来会很不清晰,我们使用已经封装好的Inception来搭建GoogLeNet网络 关键点 关键点在于I…

Open WebUI 是什么

Open WebUI 是什么 Open WebUI 是一个可扩展、功能丰富且用户友好的自托管 AI 平台,旨在完全离线运行。它支持各种 LLM 运行器,如 Ollama 和 OpenAI 兼容的 API,并内置了 RAG 推理引擎,使其成为强大的 AI 部署解决方案。 https://github.com/open-webui/open-webui 🚀 …

ssh与服务器

目录 前言&#xff1a; 一、密码连接 二、密钥对连接 1.将公钥放在服务器 2.ssh连接 三、禁用密码 1.进入服务器/etc/ssh文件夹 2.打开sshd_config文件&#xff0c;进行如下配置 3.有可能还需要更改其他文件夹 4.重启ssh服务 四、config 五.ssh与github 1.本地创建…

图像处理篇---图像处理中常见参数

文章目录 前言一、分贝&#xff08;dB&#xff09;的原理1.公式 二、峰值信噪比&#xff08;PSNR, Peak Signal-to-Noise Ratio&#xff09;1.用途2.公式3.示例 三、信噪比&#xff08;SNR, Signal-to-Noise Ratio&#xff09;1.用途2.公式3.示例 四、动态范围&#xff08;Dyna…

剖析IO原理和零拷贝机制

目录 1 Linux的五种IO模型1.1 模型调用的函数1.1.1 recv函数1.1.2 select函数1.1.3 poll函数1.1.4 epoll函数1.1.5 sigaction函数 1.2 IO模型1.2.1 阻塞IO模型1.2.2 非阻塞IO模型1.2.3 IO复用模型1.2.4 信号驱动IO模型1.2.5 异步IO模型1.2.6 IO模型比较 2 Java的BIO、NIO、AIO2…

DeepSeek 助力 Vue 开发:打造丝滑的滑块(Slider)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

vivado 在ip引出来emio 没有显示

原因是IP核 block design 里面需要ctrs 保存了 再generate output

C进阶 自定义类型

目录 前言 一 结构体 二 结构体的存储 三 位段 四 枚举 五 联合体 总结 前言 我们之前学习的int char double ......都是内置类型&#xff0c;但是我们今天所学习的是自定义类型&#xff0c;比如联合体&#xff0c;结构体&#xff0c;枚举 一 结构体 结构体是一…

四、综合案例(Unity2D)

一、2D渲染 1、2D相机基本设置 上面是透视&#xff0c;下面是正交 2、图片资源 在Unity中&#xff0c;常规图片导入之后&#xff0c;一般不在Unity中直接使用&#xff0c;而是转为精灵图Sprite 将图片更改为即可使用Unity内置的图片切割功能 无论精灵图片是单个的还是多个的…