天天看点

loki::allocator

文章目录

    • 1. loki::allocator 结构
    • 2. loki::allocator 使用实例
    • 3. loki::allocator 具体实现
      • 3.1 Chunk 部分实现
      • 3.2 FixedAllocator 部分实现
    • 4. loki::allocator 总结

loki::allocator 是由C++编委会一成员所写,可找到的最新版本是 loki-0.1.7.exe,所以从未发行过。但是并不妨碍学习其中的设计思路和实现方法。其实现颇有暴力美学的味道,但是又能够较好的实现功能,相比于std::alloc,其能够对所管理的内存进行 delete[] 操作(即进行内存回收,交给os,详细见下),同时由于版本迭代很少,也有一定数量的 bug 也会在下面的内容中予以指出。

源码地址见:https://github.com/zhanglipingGitHub/BeautifulCode

同时推荐看下:【C++内存管理】loki::allocator 源码分析

1. loki::allocator 结构

loki::allocator 可分为三个嵌套结构,自下而上分别为 Chunk,FixedAllocator,SmallObjAllocator。

loki::allocator

2. loki::allocator 使用实例

loki::allocator
loki::allocator

上图中chunk改为block。下图表示的是以p5,p6,p4,p7的顺序对指针所指位置进行 Deallocate() 之后的结果,具体为

myAlloc.Deallocate(p#,64);

,所得到的结果图即是下图。

loki::allocator

3. loki::allocator 具体实现

3.1 Chunk 部分实现

loki::allocator中的Chunk的实现细节如下,分为Fixed::allocator::Chunk::Init(),Reset() 和 Release()。其中 Release() 确实是实现了对回收内存的释放。

loki::allocator

Chunk::Allocate()实现如下,即是由firstAvailableBlock的序号和pData的位置来计算要分配的内存地址的位置,同时减少block存量(–blocksAvailableBlock_)。

loki::allocator

Chunk::Deallocate()的实现如下。指针强转之后,将firstAvailableBlock_更改为p的序号,增加block的存量(++blocksAvailableBlock_)。

loki::allocator

3.2 FixedAllocator 部分实现

Allocate()逻辑为:若是当前Chunk仍有block可供分配,则直接分配;若是没有则遍历所有的Chunks,若是找到有可分配内存的Chunk则进行分配,若是没有找到则重新申请一块内存空间,并将其初始化为Chunk,再进行分配。

Deallocate() 则是先调用VicinityFind ( p ) 函数找到需要 deallocate 的位置再调用 DoDeallocate(p)进行内存释放操作。

loki::allocator

VicinityFind()函数主要用于查找 指向所要进行回收的内存 的 指针 所对应的 Chunk是哪个。从FixedAllocator所指的deallocChunk(即上次释放中所指定的chunk)向上和向下进行暴搜,直至找到p所处的chunk为止,再将上次请求释放的空间给释放掉,更新deallocChunk信息。同时有个bug就是,如果p不属于FixedAllocator所管理的内存空间,则会导致死循环。

loki::allocator

FixedAllocator::DoDeallocate()是FixedAllocator进行内存回收的函数。其中调用了Chunk的 Deallocate() 进行内存空间回收 和 Release() 进行内存空间归还给os 的操作。具体的归还细节不表,但是可看出是使用了 Defering 技法的。此外,该版本下的 bug 也在图片中已经写明。

loki::allocator

4. loki::allocator 总结

  • 曾有两个 bug,见 FixedAllocator 部分实现章节,其中的 VinicityFind() 和 DoDeallocate() 的函数实现;
  • 精简强悍,但是手段暴力(

    for(;;)

    的使用);
  • 使用array代替list,即数组(vector)代替链表,同时使用索引(index)下标代替指针(pointer);
  • 能够以简单的方式(

    deallocChunk_->blocksavAilable_ == numBlocks

    )判定是否进行 chunk 全回收,进而将 memory 归还给操作系统;
  • 有Deferring(暂缓归还)的能力;
  • 和 std::alloc 一样,是一种 allocator,用来分配大量小块不带 cookie 的 memory blocks,由 SBH/malloc 分配的内存带有 cookie,它的最佳客户是容器,但是其本身却 has-a vector。

相比于之前分析的 std::alloc 的内存管理:

  • std::alloc 一旦向 OS 索取了新的 chunk,就不会还给 OS 了,一直在自己的掌控之中。因为它里面的指针拉扯比较复杂,几乎不可能去判断一块 chunk 中给出去的 block 是否全部归还了。但是 loki::allocator 通过利用一个 blocksAvailable_ 变量,就很容易的判断出某一块 chunk 中的 block 是否已经全部归还了,这样就可以归还给 OS。
  • std::alloc 只负责一些特定 block size 的内存管理。如果客户端需要的 block size 它并不支持,那个客户端的 block size 会被取整到最接近的大小 (当然前提是小于它所能够分配的最大的 block size);但是 loki::allocator 能够为不大于最大 block size 的所有 block size 服务。

继续阅读