Obstacks是GUN lib中实现的内存池,在基于GNU的系统中可以直接使用,想要深入了解GNU Obstacks的可以参阅参考资料。
在阅读mlocate命令源码时接触到了Obstack,网上查找资料时没有找到中文版本的资料,只能根据上面的官方英文参考资料,整理记录一点笔记。
1. 创建obstacks
操作obstacks的所有函数都在定义在头文件obstack.h中。
struct obstack
结构体strcut obstack代表一个obstack,它并不包含对象本身,不应该直接访问这个结构体的内容。
所有操作obstack的函数都需要指明使用哪个obstack,使用struct obstack*指明。
obstack中的对象被打包放在非常大的内存块中,这些块被称作chunks,struct obstack中保存有一个指向正在使用的chunks链表的指针。
一旦最后一个chunk中空间不足时,obstack就会获得一个新的chunk。obstack会自动的管理chunks,所以你不需要关心他们,但你需要指出哪个obstack需要获得一个chunk。
2. 准备开始使用obstack
在每个需要使用obstack的源文件中加入#include
使用obstack前必须初始化这个obstack,使用obstack_init
int obstack_init (struct obstack *obstack-ptr)
使用obstack_init前必须定义obstack_chunk_alloc和obstack_chunk_free。
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
3. 在一个obstack上申请空间
最直接的方式是使用obstack_alloc
void * obstack_alloc (struct obstack *obstack-ptr, int size)
申请空间并填充内容,使用obstack_copy
void * obstack_copy (struct obstack *obstack-ptr, void *address, int size)
申请空间并使用address指向的内存填充
void * obstack_copy0 (struct obstack *obstack-ptr, void *address, int size)
功能同上,区别是会在最后追加一个'\0'
4. 释放obstack中的对象
obstack_free,因为obstack中包含很多对象,释放其中一个会自动释放同一个obstack中在它之后创建的对象。
void obstack_free (struct obstack *obstack-ptr, void *object)
如果object为空,那么这个obstack中申请的所有空间都会被释放。
需要注意的是,object为空指针时,obstack会成为一个未初始化的obstack。想要释放所有空间并且保留一个有效的obstack,使用obstack_free释放obstack中第一个对象的地址,用法:
obstack_free (obstack_ptr, first_object_allocated_ptr);
5. 增长型对象
内存在obstack chunks中是连续的,这就让一步一步创建一个对象成为了可能,可以做到一点一点在这个对象最后添加一个或多个字节。你不需要提前知道你将要放入多少数据到这个对象中。我们称这样的技术为增长型对象。
增长型对象的真实地址只有在完成后才能知道。
当obstack正在用来创建一个增长型对象时不可以用来创建普通对象。
下面是对growing object的操作函数:
void obstack_blank (struct obstack *obstack-ptr, int size)
添加空白到growing object中
void obstack_grow (struct obstack *obstack-ptr, void *data, int size)
添加已有数据growing object中
void obstack_grow0 (struct obstack *obstack-ptr, void *data, int size)
添加已有数据,并在最后添加 '\0'
void obstack_1grow (struct obstack *obstack-ptr, char c)
添加一个字符
void obstack_ptr_grow (struct obstack *obstack-ptr, void *data)
添加一个指针本身,大小为sizeof (void *)
void obstack_int_grow (struct obstack *obstack-ptr, int data)
添加一个int型变量,大小为sizeof(int)
void * obstack_finish (struct obstack *obstack-ptr)
完成一个增长型对象,并返回最终地址。
int obstack_object_size (struct obstack *obstack-ptr)
返回一个增长型对象当前大小,单位为byte。对象如果已经完成会返回0。
想要释放一个正在增长的对象,需要先完成它,然后释放它,比如:
obstack_free (obstack_ptr, obstack_finish (obstack_ptr));