linux stl内存池的应用

2023-10-30

在stl里面,stl对容器中元素内存的分配,与元素的构造、析构过程进行了分离

 c++ 在全局定义了 operator new(size_t size), 调用malloc(size)

operator new(size_t size,void* buf) 什么也不做直接return buf

operator delete(void* buf); 调用free(buf)

对于ClassA* ptr = new ClassA(),编译器步骤为(分配内存+调用构造函数)

void * mem=operator new(sizeof(ClassA));

ClassA* ptr=(ClassA*)mem;

ptr->ClassA::ClassA();

对于new(_mem) ClassA(), 编译器步骤为(使用已分配的内存(内存需要对齐) + 调用构造函数,相当于分离分配过程)

void* mem = operator new(sizeof(ClassA),_mem); //其实什么也没做,直接返回mem

ClassA* ptr=(ClassA*)mem;

ptr->ClassA::ClassA(); //通过指针直接调用时,无法编译

可以使用stl里面实现的标准内存分配器std::allocator

在windows上其使用_Default_allocate_traits实现空间分配,比较直接使用 operator new直接分配,施放则是直接调用_Deallocate函数使用operator delete释放

在linux上是使用new_allocator类进行分配、释放,也是直接operator new、operator delete

allocator<Foo> alloc;
//Allocate memory for one or n objects,根据Foo对象内存对齐后的原始内存
auto p = alloc.allocate(1);
//Construct an object of Foo on allocated memory block p, by calling one of Foo's constructors
alloc.construct(p, args, ...);

//OK, p now points to a Foo object ready for use...

//Call Foo's destructor but don't release memory of p
alloc.destroy(p);
//Release memory
alloc.deallocate(p, 1);

在linux上,编译器版本为9.4.0扩展了mt_alloc,适用于单线程、多线程,具有内存池功能; 分为一级管理与二级管理,一级管理直接new、delete,二级管理采用内存池。默认情况大于128bytes使用一级管理,小于采用二级管理;当采用二级管理时,每次申请都是先查询释放链表有没有释放过的,有释放过的先复用,然后才是在内存池中割一块新的,或者重新分配一块

#include <ext/mt+allocator.h>
int main(argc , char **argv)
{
    //__ommon_pool_policy模板参数bool表示是否用于多线程
    typedef __gnu__cxx::__mt_alloc<<XXXX>, __gnu_cxx::__common_pool_policy<__gnu_cxx::_pool, false>> MtPoolAlloc;
    typedef __gnu_cxx::__pool_base::_Tune MtPoolAllocTune;
    
    MtPoolAlloc alloc;
    /*
    size_t _M_align; //字节对齐
    size_t _M_max_bytes; //默认为128,表示128字节以上的用new直接分配
    size_t _M_min_bin;//可分配的最小的内存大小,默认为8
    size_t _M_chunk_size;//每次从os申请的内存块的大小,默认为4096 - 4 *sizeof(void*)
    size_t _M_max_threads;//可支持的最多的线程数,默认4096
    size_t _M_freelist_headroom;//单线程能保存的空闲块的百分比,默认10%
    bool   _M_force_new;//是否直接使用new和delete
    */
    MtPoolAllocTune opt{8, sizeof(XXXX), sizeof(XXXX), 4096 - 4 * sizeof(void*), 1, 10, false};
    //alloc._M_get_options可以返回正在使用的,修改部分也可以
    alloc._M_set_options(opt);
    auto *tt1 = alloc.allocate(1);
    alloc.construct(tt1, 1, 2);//调用构造函数
    std::cout << reinterpret_cast<unsigned long long>((void*)tt1) << std::endl;
    alloc.destroy(tt1); //调用析构函数; 如果析构是虚函数,没有调用构造函数的话,这里会崩溃
    alloc.deallocate(tt1, 1); //放回内存池
    tt1 = alloc.allocate(1);
    alloc.construct(tt1, 1, 2);//调用构造函数
    std::cout << reinterpret_cast<unsigned long long>((void*)tt1) << std::endl;
    alloc.destroy(tt1);
    alloc.deallocate(tt1, 1); //放回内存池
}

运行结果为:

94504784214136
XXXX() //构造函数打印
~XXXX() //析构函数打钱
94504784214136
XXXX() //构造函数打印
~XXXX() //析构函数打钱

与allocator这一类分配器,相配对的还有专门的stl算法函数,如uninitialized_copy、uninitialized_copy_n、uninitialized_fill、uninitialized_fill_n等,都是把输入源拷贝到已分配(但未初始化)的内存上,在对应位置直接调用对应的类的拷贝构造函数

自定义allocator,范例如下

#include <vector>
#include <ext/mt_allocator.h>

template<typename T>
class SelfAlloc{
    public:
    typedef T value_type;

    SelfAlloc() = default;

    template<typename T1>
    SelfAlloc(const SelfAlloc<T1>& other){}

    T* address(T &x){
        return static_cast<T*>(&x);
    }
    const T* address(const T &x){
        return static_cast<const T*>(&x);
    }

    T* allocate(size_t _n,const void* hit=0 ){
        return static_cast<T*>(::operator new(_n*sizeof(T)));
    }

    void deallocate(T* p, size_t _n){
        ::operator delete(p);
    }

    size_t max_size()const throw(){
        return static_cast<size_t>(std::numeric_limits<int>::max()/sizeof(T));
    }

    template<typename _Up, typename... _Args>
    void construct(_Up* __p, _Args&&... __args){
        ::new((void *)__p) _Up(std::forward<_Args>(__args)...);
    }

    template<typename _Up>
    void destroy(_Up* __p){
        __p->~_Up();
    }
};

template<typename T>
inline bool operator==(const SelfAlloc<T> &, const SelfAlloc<T> &){
    return true;
}

template<typename T>
inline bool operator!=(const SelfAlloc<T> &, const SelfAlloc<T> &){
    return false;
}

int main(int argc, char **argv){
    std::vector<int, SelfAlloc<int>> ewefwi; 
    ewefwi.push_back(2);
    ewefwi.push_back('a');
    auto wefwff = ewefwi;
    std::vector<int, SelfAlloc<int>> jlllll;
    jlllll = ewefwi;

    return 0;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux stl内存池的应用 的相关文章

随机推荐

  • 配置宝塔,搭建网站

    配置宝塔面板 一 获取虚拟机的IP地址 打开虚拟机 输入命令 ip addr获取IP地址 二 使用cmd运行获取宝塔面板信息 1 运行cmd 并输入命令ssh root 获取的IP地址 2 输入登录密码 3 获取宝塔的命令行 4 输入14命
  • 跨专业计算机研究生如何毕业论文,跨专业考研论文要求

    跨专业考研写几篇论文 跨专业考研论文要求 近几年 跨专业考研得的队伍愈发壮大 许多考生不仅会跨相关专业 甚至还有人进行文理科间得的 大转行 跨专业报考得的难度系数在考研中是比较大得的 既有 满盘皆输 得的危险 也可能会带来出奇制胜得的效果
  • Column ‘status_type‘ in where clause is ambiguous

    多表查询时 由于字段名字有重复 所以需要指定那张表的字段
  • 学习笔记《你不知道的JavaScript上卷》第一章 作用域是什么 1.2理解作用域

    引擎 从头到尾负责整个 JavaScript 程序的编译及执行过程 编译器 引擎的好朋友之一 负责语法分析及代码生成等脏活累活 详见前一节的内容 作用域 引擎的另一位好朋友 负责收集并维护由所有声明的标识符 变量 组成的一系列查 询 并实施
  • 小程序开发工具全新上线

    导语 为了让开发者更高效地开发和发布小程序 微信开发者工具全新改版上线 并新增测试系统 腾讯云工具 运维性能监控 小程序分阶段发布 WXS脚本语言等 01 微信开发者工具 为提升小程序开发体验 帮助开发者更高效地开发小程序代码 微信开发者工
  • JDBC自定义框架

    自定义JDBC框架 定义必要的信息 获取数据库的连接 释放资源都是重复的代码 在操作JDBC时通常都是执行SQL语句就可以了 所以需要抽取出来一个模板类来封装一些方法 Update Query 专门执行增删改查的SQL语句 简化使用步骤 D
  • 字符串转LocalDateTime异常

    文章目录 现象 解决方案 拓展测试 总结 现象 当使用LocalDateTime 与字符串互转异常 使用LocalDateTime 字符串必须带时分秒 public static void main String args DateTime
  • vcruntime140.dll重新安装的方法(最佳推荐方法)

    vcruntime140 dll是什么什么文件呢 为什么电脑在运行一些游戏的时候会出现丢失vcruntime140 dll 然后游戏运行失败 这个dll文件是电脑重要的运行库文件 丢失了会导致很多程序无法运行 下面将介绍vcruntime1
  • 在vue项目中使用高德地图

    1 安装高德地图插件 npm install vue amap save 2 申请高德地图账号和key 官网地址 高德开放平台 高德地图API 3 在main js中引入 引入vue amap import VueAMap from vue
  • 三维包围盒碰撞检测算法-Python(OBB-SAT)

    想实现一个检测三维包围盒是否发生碰撞的功能 因为目标是任意方向的三维包围盒 即没有和坐标轴对齐的旋转包围盒 所以考虑采用检测OBB碰撞的SAT算法 但找了很久没找到现成的python代码 就比着别人写的C 版本自己写了python的代码 1
  • CAT3、CAT4、CAT5、CAT5E、CAT6、CAT6A、CAT7和CAT8网线的介绍

    目录 1 CAT3网线 10Mbps 2 CAT4网线已淘汰 3 CAT5 网线 100MHz 100Mbps 4 CAT5E网线 100MHz 1000Mbps 5 CAT6网线 250MHz 1000Mbps 6 CAT6A 网线 50
  • C#程序中进行FTP上传下载时出现的问题

    在C 程序中 进行ftp操作时容易出现的问题 The remote server returned an error 550 File unavailable e g file not found no access 解决方法 首先 查看登
  • matlab中的twomodegauss函数-双峰高斯函数

    文章搬运于 http blog sina com cn s blog 4fc818ea0101l8kn html function p twomodegauss m1 sig1 m2 sig2 A1 A2 k TWOMODEGAUSS Ge
  • STM32在FREEOS进行IAP跳转死机

    现象 STM32使用串口IAP进行跳转 发现APP程序用freeos编写的时候 程序跳转完成后就死机了 IAP程序在跳转前都关闭了中断和复位了使用的外设 已经验证跳转到裸机程序没有问题 FREEOS的程序在main函数开始就进行了开启中断和
  • wireshark取证案例学习笔记

    此文对应wireshark取证分析练习题前5道 题目来源 及PACP包下载地址 自己学习的一点笔记和心得 记录下来以免遗忘 练习题1的任务书解答 某公司怀疑其雇员张小花是其竞争对手派来的商业间谍 张小花访问了公司的一个机密配方 安保人员担心
  • Windows删除本地svn项目文件夹

    在window下 打开DOS命令窗口 进入需要清除svn的文件目录 输入如下命令 for r a in do if exist a svn rd s q a svn
  • ecs云服务器网站迁移,ecs云服务器网站迁移

    ecs云服务器网站迁移 内容精选 换一换 备案是中国大陆的一项法规 使用大陆节点服务器提供互联网信息服务的用户 需要在服务器提供商处提交备案申请 根据工信部 互联网信息服务管理办法 国务院292号令 和工信部令第33号 非经营性互联网信息服
  • GNU协议条款

    感谢原文作者 http v266 yo2 cn articles gnu E7 99 BE E7 A7 91 E5 90 8D E8 AF 8D E8 A7 A3 E9 87 8A html GNU 包含3个协议条款 GPL GNU通用公共
  • 最简单的DRM应用程序 (page-flip)

    在上一篇 最简单的DRM应用程序 double buffer 中 我们了解了DRM更新图像的一个重要接口drmModeSetCrtc 在本篇文章中 我们将一起来学习DRM另一个重要的刷图接口 drmModePageFlip drmModeP
  • linux stl内存池的应用

    在stl里面 stl对容器中元素内存的分配 与元素的构造 析构过程进行了分离 c 在全局定义了 operator new size t size 调用malloc size operator new size t size void buf