C++ STL内存池

内存池出现原因:内存碎片

首先我们需要明确, 内存池的目的到底是什么? 首先你要知道的是, 我们每次使用new T来初始化类型T的时候, 其实发生了两步操作,

  1. 一个叫内存分配, 这一步使用的其实不是new而是operator new(也可以认为就是C语言中的malloc), 这一步是直接和操作系统打交道的, 操作系统可能需要经过相对繁琐的过程才能将一块指向空闲内存的指针返回给用户, 所以这也是new比较耗时的一部分,
  2. 而第二步就是使用构造函数初始化该内存, 这是我们比较熟悉的.

既然内存分配耗时, 那我们很容易想到的就是一次性分配一大块内存, 然后在用户需要的时候再划分其中一部分给用户, 这样的话,一次分配, 多次使用, 自然而然提高了效率, 而用来管理这所谓的一大块内存的数据结构, 也就是今天我们要说的内存池.

另外一个好处在于, 频繁地使用new将导致系统内存空间碎片化严重, 容易导致的后果就是很难找到一块连续的大块内存, 造成内存碎片(非连续),空间利用率低.

内碎片是指分配给作业的存储空间中未被利用的部分,外碎片是指系统中无法利用的小存储块。

C++ STL内存池

1.内存申请流程图

小于等于128k的用第二级分配器;

大于128k的用第一级分配器

C++ STL内存池

2. 第一级配置器:

第一级採用malloc、free;

此外,这个配置器提供了当内存配置错误时的处理函数oommalloc,这个函数会调用_malloc_alloc_oom_handler()这个错误处理函数,去企图释放内存,然后重新调用malloc分配内存。如此循环,直到分配成功,返回指针(所以再一定程度上提高内存分配成功)。

3. 第二级配置器

使用自由链表(free-list)技巧。主动将不论什么小额区块的内存需求量上调至8的倍数。如需求30,则上调至32。

free-list节点结构

union obj 
{
     union obj * free_list_link;     //下一个节点的指针
     char client_data[1];                    //内存首地址
}

有16个free-lists。各自管理大小分别为8、16、24、32、40、48、56、64、72、80、88、96、104、112、120、128 bytes的小额区块。

C++ STL内存池

释放内存

C++ STL内存池

所以最终内存池的思路其实是这样的:

  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. 找不到空间, 抛出异常(代码中并未给出, 只是给出了注释)

  1. 用户调用deallocate释放内存空间, 如果要求释放的内存空间大于128bytes, 直接调用free.

  2. 否则按照其大小找到合适的自由链表, 并将其插入.

特点其实是这样的 :

  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
原文链接: https://www.cnblogs.com/xiaoxue126/p/9007047.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/273509

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月14日 下午11:41
下一篇 2023年2月14日 下午11:41

相关推荐