本章主要谈到的是内存管理接口及其实现,接口的实现使用了基于内存池(arena)的算法,其分配的内存来自一个内存池,使用完毕后立即释放整个内存池。
利用基于内存池的分配器,不必像malloc/free那样,对每次调用malloc返回的指针调用free,只需要一个调用,即可释放上一次释放操作以来内存池中分配的所有内存。运用合用算法(applicative algorithm),一般只分配新数据结构,而不修改现存的数据结构。
1、基于内存池的方案有两个缺点:它可能使用更多的内存,而且可能造成悬挂指针。如果一个对象通过错误的内存池分配,而在程序用完该对象之前相应的内存池已经释放,程序将引用未分配的内存或已经被其他内存池(可能是毫无关系的内存池)重用的内存。还有一种可能,即内存池中分配的对象的释放时间迟于预期,这会造成内存泄露。但实际上,内存池的管理师如此容易,以至于这些问题很少发生。
2、接口(含有两个异常,以及管理内存池并从内存池中分配内存的函数)
extern const Except_T Arena_NewFailed;
extern const Except_T Arena_Failed;
内存池通过下列函数创建和销毁:
extern T Arena_new (void);
extern void Arena_dispose(T *ap);
extern void *Arena_alloc(T arena,long nbytes,const char *file,int line);
extern void *Arena_calloc(T arena,long count,long nbytes,const char *file,int line);
extern void *Arena_free(T arena);
3、基于内存池的分配将许多显式释放操作合并为一个。垃圾收集器(garbage collector)更进一步:它们避免了所有的显式释放操作。在具备垃圾收集器的语言中,程序员几乎可以忽略内存分配,内存分配bug(几乎)不可能发生。这样,内存空间将根据需要自动地回收(通常是在内存分配请求无法满足时)。垃圾收集器会找到所有被程序变量引用的内存块,以及这些块中的字段引用的所有内存块,以此类推。这些是可访问的内存块,其他的内存块是不可访问的,因而可以重用。