文件Stl_alloc.h
 文件内容介绍:此文件主要包含了为stl容器分配空间的一些函数,包括在内存溢出时 
的一些相关处理。
    此文件前面进行系统类型的判断和是否使用多线程或者pthreads等判断
List:
名称 类型 返回值和参数 功能
__malloc_alloc_template Class  分配内存模板,模板带有一个模板参数为<int inst>,
为第一级配置
__malloc_alloc_template
::oom_malloc Function
private Return:Void*(表明分配的内存的地址)
Parm:size_t(表明要分配的内存的大小) 分配内存函数,当内存出现溢出时调用oom--
out of memory。首先声明一个指针函数(其实这个指针函数在之前的模板中定义过
__malloc_alloc_oom_handler,当内存溢出时使用,其stl_alloc.h文件中给出的默认是0
,为空,当然用户也可以自己指定。alloc.h给出了处理函数__STD::
__malloc_alloc_oom_handler
)如果此函数指针仍然为空,则抛出分配内存异常,如果不为空则调用该函数,然后使用
malloc分配size_t大小的内存,将内存的首地址返回给此函数。在for
死循环中不断分配直到成功见C++ new-handler
__malloc_alloc_template
::oom_realloc Function
private Return :void*(表明分配的内存的地址)
Parm:void*(要重新分配的内存的地址);size_t(重新分配内存的大小) 
重新分配内存函数,当内存出现溢出时调用oom--out of memory
。首先声明一个指针函数(其实这个指针函数在之前的模板中定义过
__malloc_alloc_oom_handler,当内存溢出时使用,其stl_alloc.h文件中给出的默认是0
,为空,当然用户也可以自己指定。alloc.h给出了处理函数__STD::
__malloc_alloc_oom_handler
)如果此函数指针仍然为空,则抛出分配内存异常,如果不为空则调用该函数,然后使用
realloc分配size_t大小的内存,将内存的首地址返回给此函数。见C++ new-handler
__malloc_alloc_template::
__malloc_alloc_oom_handler Function pointer
Private Return:void
Parm:void 如果在stl_config.h文件中define过__STL_STATIC_TEMPLATE_MEMBER_BUG
,那么声明这个函数指针,当分配内存出现错误的时候进行一些处理
__malloc_alloc_template::allocate Function
Public Return:void*(分配内存后的内存首地址)
Parm:size_t(需要分配的内存的大小) 首先使用malloc分配size_t
大小的内存,如果分配成功,返回malloc返回值,如果失败则转到调用函数oom_malloc(
size_t)
__malloc_alloc_template::deallocate Function
Public Return:void
Parm:void*p(释放内存的指针);size_t(未使用,表示p所指向的内存大小) 调用free
释放参数一所指的内存
__malloc_alloc_template::reallocate Function
Public Return:void*(分配的内存的地址)
Parm:void*p(需要重新分配的内存地址内存的指针);size_t(未使用,表示p原先的大小)
;sieze_t(表示新分配的内存大小) 使用realloc进行重新分配内存,如果成功返回
realloc分配的内存的首地址,如果失败则调用函数oom_realloc函数处理
__malloc_alloc_template:: (* set_malloc_handler()) Function
Public Return:void (*)()(返回原先的内存错误处理函数)
Parm:Void(*)()(内存出错处理函数) 首先声明一个void(*old)()函数,将原先的
__malloc_alloc_oom_handler赋值给它,然后将f赋值给__malloc_alloc_oom_handler
,然后返回old。
注:此函数可以如此理解
typedef  void (*fp)();
static fp set_malloc_handler(fp f);
如同fp为一个类型,然后声明f和set_malloc_handler变量一样,直接套进去就可以(
详见《C与指针》、《C专家编程》)
malloc_alloc Object  typedef __malloc_alloc_template<0> malloc_alloc;
simple_alloc class  简单的内存管理,含有模板参数<class T, class Alloc>,Alloc
表示的是一个内存管理的类型,如上面的__malloc_alloc_template
simple_alloc::allocate Function
Public、static Return:T*返回类型为T的内存指针
Parm:size_T
 如果n==0,那么返回0,否则调用Alloc的allocate函数分配n*(sizeof(T))
大小内存,并强制转换为T(*)类型返回。
(将C中的分配特定类型的n个大小内存特化成一个函数)
simple_alloc::allocate Function
Public、static Return:T*返回指针类型为T的内存首地址
Parm:void 重载上面的函数,返回大小为sizeof(T)的内存块,并强制转换成(T*)
指针返回
simple_alloc::deallocate Function
Public、static Return:void
Parm:T*(表示释放内存的首地址);size_t(表示释放的类型为T的内存大小) 如果n!=0
则调用Alloc的deallocate(p,sizeof(T)*n)进行内存释放
simple_alloc::deallocate Function
Public、static Return:void
Parm:T*(表示释放内存的首地址) 则调用Alloc的deallocate(p,sizeof(T))进行内存释放
debug_alloc Class  这个是为调试准备的,检查传入的size
参数是否符合特定的要求,使用assert
报告错误。如果没有检查的必要还是使用基本的内存分配器好点。带有一个模板参数<
class Alloc>
debug_alloc ::extra Enum
Private 值为8 存储空间的单位,应该足够大以保证内存对齐(对齐:从以n
为单位的地指处开始存取)
debug_alloc ::allocate Function
Public、static Return:void*(内存分配的首地址)
Parm:size_t n(分配的大小) 使用Alloc::allocate分配n+extra个内存的大小(
我认为加上extra是为了防止n为0,看后面操作),然后给这个内存的起始地址处赋值为n(
所以避免n为0时,内存错误)。然后以分配的地址+extra为返回值
debug_alloc :: deallocate Function
Public、static Return:void
Parm:void*p(为指向释放内存的地址);size_t n(表示释放内存的大小) 由于上面的
allocate在返回值上加了extra,所以在这里首先减去extra
,然后取出这个计算后的地址的值,用assert判断其是否和n相等(allocate存入的n)
,如果相等则使用Alloc(p,n+extra)释放内存
debug_alloc :: reallocate Function
Public、static Return:void*(内存分配的首地址)
Parm:void*p(需要重新分配内存的首地址);size_t old_sz(原先内存大小);size_t
new_sz(重新分配的内存的大小) 前面两步如deallocate函数,只不过n换成old_sz
,然后使用Alloc函数reallocate重新分配内存(参数为p,old_sz+extra,new_sz+extra)
,并取得返回值result,并在result中放入值new_sz,最后返回result+extra地址
__ALIGN(全局) Enum 8bytes 
小型区块的上调边界(每一个小型区块指向一个一特定大小为单位的链表,详见表末说明
。)
__MAX_BYTES(全局) Enum 128bytes 第一级配置器和第二级配置器的分界字节数
__NFREELISTS(全局) Enum __MAX_BYTES/__ALIGN Free-lists个数
__default_alloc_template Class  STL
使用的是二级配置器,这个配置器是默认的。第一个模板参数是说明是否是多线程,类存?
渲檬窍叱贪踩模诙霾问ㄎ纯芍?
__default_alloc_template ::__ALIGN Enum
Private 同全局 如果全局中没有定义此enum,则在类中定义
__default_alloc_template ::__MAX_BYTES Enum
Private 同全局 同上
__default_alloc_template ::__NFREELISTS Enum
Private 同全局 同上
__default_alloc_template ::ROUND_UP Function
Private、static Return:size_t(在free_list中的节点的大小)
Parm:size_t bytes(要分配的内存大小) 由于在free_list中维护的16个节点,而16
个节点的大小已经规定好,详见总结中 ,而分配的结果必须位于这16
个值当中,所以根据bytes传入的值的大小来取离此值最近的闭其大的值作为返回值。
__default_alloc_template :: obj Union
Private  详见总结
__default_alloc_template ::free_list private  内存链
__default_alloc_template ::refill Private
Static Return:void*(地址)
Parm:sizet_t n(所要分配的内存块的大小) 当allocate()发现freelist
中没有可用区块时,调用refill(),准备为freelist
重新填充空间,新的空间将取自内存池(经由chunk_alloc完成)缺省取得20
个新节点,但万一内存池空间不足,获得的节点数可能少于20
__default_alloc_template ::chunk_alloc Private
Static Return:char*(返回内存池分配的地址)
Parm:size_t size(内存块的大小);int& nobjs(分配的块的个数) 首先使用end_free,
first_free计算出当前情况下内存池共有的字节数bytes_left,然后判断,如果
bytes_left>=*nobjs,那么就直接返回start_free的值,然后将start_free的值调整为
start_free+bytes_left.
如果内存池剩下的内存小于*nobjs,但是大于等于size,那么就分配bytes_left/size
个元素,调整start_free的值,返回start_free地址。如果内存池中的剩余地址小于size
,则首先产生一个 大于nobjs*2的值,将剩余的内存尽可能大的编进free list
里面。然后使用malloc分配内存,如果成功,调整heap_size,然后调整end_free
大小,返回值为重新调用自己产生的地址。如果malloc分配失败,则释放freelist
中较大的块,然后返回(调用自己)(如此循环)
__default_alloc_template :: start_free Private
Static Type:char* 内存池的首地址,初值为0
__default_alloc_template :: end_free Private
Static Type:char* 内存池的尾地址,初值为0
__default_alloc_template :: heap_size Private
Static Type: size_t 内存池使用的堆栈大小,初值为0
__default_alloc_template :: __lock Private
 Return:void
Parm:unsigned long* 加锁,详细未查
__default_alloc_template :: __unlock Private Return:void
Parm:unsigned long* 解锁,详细未查
Friend class lock  属于__default_alloc_template的内部类 构造函数调用
__NODE_ALLOCATOR_LOCK宏,而这个函数调用__lock(…),析构函数调用
__NODE_ALLOCATOR_UNLOCK宏,而这个宏调用__unlock(…)函数
注:类型为类、函数、仿函数等等,如果是成员函数则在名称前加上所属类并在类型上写上
其权限,总之名称包括可以唯一确定该元素
内存图:
STL源码阅读1——内存分配_第1张图片