C++ STL内存池
内存池出现原因:内存碎片
首先我们需要明确, 内存池的目的到底是什么? 首先你要知道的是, 我们每次使用new T来初始化类型T的时候, 其实发生了两步操作,
- 一个叫内存分配, 这一步使用的其实不是new而是operator new(也可以认为就是C语言中的malloc), 这一步是直接和操作系统打交道的, 操作系统可能需要经过相对繁琐的过程才能将一块指向空闲内存的指针返回给用户, 所以这也是new比较耗时的一部分,
- 而第二步就是使用构造函数初始化该内存, 这是我们比较熟悉的.
既然内存分配耗时, 那我们很容易想到的就是一次性分配一大块内存, 然后在用户需要的时候再划分其中一部分给用户, 这样的话, 一次分配, 多次使用, 自然而然提高了效率, 而用来管理这所谓的一大块内存的数据结构, 也就是今天我们要说的内存池.
另外一个好处在于, 频繁地使用new将导致系统内存空间碎片化严重, 容易导致的后果就是很难找到一块连续的大块内存, 造成内存碎片(非连续),空间利用率低.
内碎片是指分配给作业的存储空间中未被利用的部分,外碎片是指系统中无法利用的小存储块。

1.内存申请流程图
小于等于128k的用第二级分配器;
大于128k的用第一级分配器

2. 第一级配置器:
第一级採用malloc、free;
此外,这个配置器提供了当内存配置错误时的处理函数oom*malloc,这个函数会调用*_malloc_alloc_oom_handler()这个错误处理函数,去企图释放内存,然后重新调用malloc分配内存。如此循环,直到分配成功,返回指针(所以再一定程度上提高内存分配成功)。
3. 第二级配置器
使用自由链表(free-list)技巧。主动将不论什么小额区块的内存需求量上调至8的倍数。如需求30,则上调至32。
free-list节点结构
union obj
{
union obj * free_list_link; //下一个节点的指针
char client_data[]; //内存首地址
}
有16个free-lists。各自管理大小分别为8、16、24、32、40、48、56、64、72、80、88、96、104、112、120、128 bytes的小额区块。

释放内存

所以最终内存池的思路其实是这样的:
1. 使用allocate向内存池请求size大小的内存空间, 如果需要请求的内存大小大于128bytes, 直接使用malloc.
2. 如果需要的内存大小小于128bytes, allocate根据size找到最适合的自由链表.
a. 如果链表不为空, 返回第一个node, 链表头改为第二个node.
b. 如果链表为空, 使用blockAlloc请求分配node.
x. 如果内存池中有大于一个node的空间, 分配竟可能多的node(但是最多20个), 将一个node返回, 其他的node添加到链表中.
y. 如果内存池只有一个node的空间, 直接返回给用户.
z. 若果如果连一个node都没有, 再次向操作系统请求分配内存.
①分配成功, 再次进行b过程
②分配失败, 循环各个自由链表, 寻找空间
I. 找到空间, 再次进行过程b
II. 找不到空间, 抛出异常(代码中并未给出, 只是给出了注释)
3. 用户调用deallocate释放内存空间, 如果要求释放的内存空间大于128bytes, 直接调用free.
4. 否则按照其大小找到合适的自由链表, 并将其插入.
特点其实是这样的 :
1. 刚开始初始化内存池的时候, 其实内存池中并没有内存, 同时所有的自由链表都为空链表.
2. 只有用户第一次向内存池请求内存时, 内存池会依次执行上述过程的 1->2->b->z来完成内存池以及链表的首次填充, 而此时, 其他未使用链表仍然是空的.
3. 所有已经分配的内存在内存池中没有任何记录, 释放与否完全靠程序员自觉.
4. 释放内存时, 如果大于128bytes, 则直接free, 否则加入相应的自由链表中而不是直接返还给操作系统.
参考文章:
https://www.cnblogs.com/zsychanpin/p/6936810.html
https://www.cnblogs.com/nzhl/p/5753728.html
C++ STL内存池的更多相关文章
- C++技术问题总结-第8篇 STL内存池是怎么实现的
STL内存池机制,使用双层级配置器.第一级採用malloc.free,第二级视情况採用不同策略. 这样的机制从heap中要空间,能够解决内存碎片问题. 1.内存申请流程图 简要流程图例如以下. ...
- sgi stl内存池实现------源码加翻译
class __default_alloc_template { enum { unit = 8 };//分配单位 后面直接用8代替 enum { max_bytes = 128 };//最大分配字节 ...
- SGI STL中内存池的实现
最近这两天研究了一下SGI STL中的内存池, 网上对于这一块的讲解很多, 但是要么讲的不完整, 要么讲的不够简单(至少对于我这样的初学者来讲是这样的...), 所以接下来我将把我对于对于SGI ST ...
- STL源码分析之内存池
前言 上一节只分析了第二级配置器是由多个链表来存放相同内存大小, 当没有空间的时候就向内存池索取就行了, 却没有具体分析内存池是怎么保存空间的, 是不是内存池真的有用不完的内存, 本节我们就具体来分析 ...
- STL源码剖析——空间配置器Allocator#3 自由链表与内存池
上节在学习第二级配置器时了解了第二级配置器通过内存池与自由链表来处理小区块内存的申请.但只是对其概念进行点到为止的认识,并未深入探究.这节就来学习一下自由链表的填充和内存池的内存分配机制. refil ...
- 基于C/S架构的3D对战网络游戏C++框架_05搭建系统开发环境与Boost智能指针、内存池初步了解
本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...
- C++STL内存管理方法(g++版)
STL作为C++的经典作品,一直备受人们关注.本文主要介绍STL的内存管理策略. 早期的STL内存管理 第一次接触STL源码是看侯捷先生的<STL源码剖析>,此书通俗易懂,剖析透彻,是极佳 ...
- nginx——内存池篇
nginx--内存池篇 一.内存池概述 内存池是在真正使用内存之前,预先申请分配一定数量的.大小相等(一般情况下)的内存块留作备用.当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续 ...
- Ogre内存池的使用和说明
大家可能会遇到一些Ogre中的内存分配的方面问题,我对这个总结了一下内存分配的方面资料. Ogre在1.7版本后,统一了内存分配策略,提供了内存是否泄漏的跟踪和内存池等比较方便开发的一些策略,目前提供 ...
随机推荐
- web开发:css基础
一.w3c架构分析 二.css三种引入 三.三种引入的优先级 四.基础选择器 五.长度单位与颜色 六.文件样式操作 七.display 一.w3c架构分析 <!DOCTYPE html> ...
- dao层取值用List<map<String,Object>>接收有序map
发现一个好玩的Map, 当需要Map有序时用java.util.LinkedHashMap接收,是有序map resultType="java.util.LinkedHashMap" ...
- solr 中文分词相关(转载)
smartcn和ik的对比,来自http://www.cnblogs.com/hadoopdev/p/3465556.html 一.引言: 年的时候,就曾经有项目涉及到相关的应用(Lunce构建全文搜 ...
- GLSLPROGRAM METALPROGRAM unity
https://docs.unity3d.com/Manual/SL-GLSLShaderPrograms.html unity里面可以直接写原生的shader 用相应的宏包起来 CGPROGRAM ...
- Python2.x与3.x版本区别Ⅱ
除法运算 Python中的除法较其它语言显得非常高端,有套很复杂的规则.Python中的除法有两个运算符,/和// 首先来说/除法: 在python 2.x中/除法就跟我们熟https://www.x ...
- 初学c++动态联编
先看一下什么是C++联编? 我觉得通俗的讲,用对象来访问类的成员函数就是静态联编. 那什么是动态联编: 一般是通过虚函数实现动态联编. 看一个动态联编的例子: 我比较懒,所以直接粘贴了MOOC视频的图 ...
- DataTable转List,DataTable转为Model对象帮助类
DataTable转List,DataTable转为Model对象帮助类 public class ModelConvertHelper<T> where T : new() { publ ...
- 如何检测域名是否被微信屏蔽 微信域名检测接口API是如何实现
微信域名检测技术的主要用户是微信域名防封,大家知道拼多多这种网站,靠诱导分享方式在微信里面摇身一变已经估值160亿美元,身价仅次于京东了 ,这是何等的速度,简直是惊为天人,but 如果你想玩微信病毒营 ...
- AT3576 Popping Balls
AT3576 Popping Balls 好题!一种以前没怎么见过的思路! %%ywy 以什么方式,什么位置统计本质不同的方案,才能不重不漏是处理所有计数问题的主心骨. 本题难以容斥.难以DP. 所以 ...
- checkbox为空
<view:qrytr> <view:qrytd width="15%" heightshow="true">请选择执法范围:</ ...