掌握内存管理对于c++/c程序员的重要性。
使用内存池的优点有:降低动态申
请内存的次数,提升系统性能,减少内存碎片,增加内存空间使用率。内存池的分类:
一、不定长内存池:
优点:不需要为不同的数据创建不同的内存池,缺点是分配出去的内存池
不能回收到池中(?)。代表有apr_pool,obstack。
二、定长内存池:
优点:使用完立即把内存归还池中。代表有Loki, Boost。
本次以sgi stl中实现的内存池作为学习对象。由于要实现的是一个C语言的内存池,所以这里用C的描述方式。喜欢C++的朋友可以直接看源文件或者《STL源码剖析》的讲解。sgi设计了二级
配置机制,第一级配置器直接使用malloc()和free()。当配置区块超过128 bytes时,则采用第一级
配置器;否则采用memory pool方式。
memory pool的整体思想是维护128/8 = 16个自由链表,这里的8是小型区块的上调边界。每个
自由链表串接的区块大小如下:
序号
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
串接区
块
8 16 24 32 40 48 56 64 72 80 88 96 104 112 120 128
范围
1-8 9-16 17-24 25-32 33-40 41-48 49-56 57-64 65-72 73-80 81-88 89-96 97-104 105-112 113-120 121-128
几个过程的思路:
一、申请过程:
2. 查找对应的链表
3. if (对应链表拥有一块以上的区块)
4. 调整链表
5. 返回第一个区块地址
6. else
7. 准备重新填充链表
8. 向内存池申请内存(指定数量的区块)
9. if (内存池申请到一个区块)
10. 返回第一个区块地址
11. else
12. 调整链表,将区块串接起来
13. 返回第一个区块地址
14. else
15. 直接用malloc()申请内存
二、释放过程:
2. 直接用free()释放
3. else
4. 查找对应的链表
5. 回收内存
三、向内存池申请内存过程:
2. 调整内存池起始位置
3. 返回空间地址
4. else if (内存池空间不能完全满足需求量,但能提供一个以上的区块)
5. 计算能够提供的最大内存
6. 调整内存池起始位置
7. 返回空间地址
8. else
9. 从内存池中压缩内存
10. 收集比size大的空间
11. 递归调用,修正nobjs
12. 再次申请内存,可能抛出异常