编辑: kr9梯 | 2016-06-22 |
size &
~(SIZE_BITS)) /* Ptr to next physical malloc_chunk. */ #define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->
size &
~SIZE_BITS) )) /* Ptr to previous physical malloc_chunk */ #define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->
prev_size) )) /* Treat space at ptr + offset as a chunk */ #define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) prev_size 字段虽然在当前 chunk 块结构体内,记录的却是前一个邻接 chunk 块的信息, 这样做的好处就是我们通过本块 chunk 结构体就可以直接获取到前一 chunk 块的信息, 从而 方便做进一步的处理操作.相对的,当前 chunk 块的 foot 信息就存在于下一个邻接 chunk 块的结构体内.字段 prev_size 记录的什么信息呢?有两种情况: 1)如果前一个邻接 chunk 块空闲,那么当前 chunk 块结构体内的 prev_size 字段记录的 是前一个邻接 chunk 块的大小. 这就是由当前 chunk 指针获得前一个空闲 chunk 地址的依据. 宏prev_chunk(p)就是依赖这个假设实现的. 2)如果前一个邻接 chunk 在使用中,则当前 chunk 的prev_size 的空间被前一个 chunk 借用中,其中的值是前一个 chunk 的内存内容,对当前 chunk 没有任何意义. 字段 size 记录了本 chunk 的大小,无论下一个 chunk 是空闲状态或是被使用状态,都可
33 以通过本 chunk 的地址加上本 chunk 的大小,得到下一个 chunk 的地址,由于 size 的低
3 个bit 记录了控制信息,需要屏蔽掉这些控制信息,取出实际的 size 在进行计算下一个 chunk 地址,这是 next_chunk(p)的实现原理. 宏chunksize(p)用于获得 chunk 的实际大小,需要屏蔽掉 size 中的控制信息. 宏chunk_at_offset(p, s)将p+s 的地址强制看作一个 chunk. 注意:按照边界标记法,可以有多个连续的并且正在被使用中的 chunk 块,但是不会有 多个连续的空闲 chunk 块,因为连续的多个空闲 chunk 块一定会合并成一个大的空闲 chunk 块. /* extract p'
s inuse bit */ #define inuse(p)\ ((((mchunkptr)(((char*)(p))+((p)->
size &
~SIZE_BITS)))->
size) &
PREV_INUSE) /* set/clear chunk as being inuse without otherwise disturbing */ #define set_inuse(p)\ ((mchunkptr)(((char*)(p)) + ((p)->
size &
~SIZE_BITS)))->
size |= PREV_INUSE #define clear_inuse(p)\ ((mchunkptr)(((char*)(p)) + ((p)->
size &
~SIZE_BITS)))->
size &
= ~(PREV_INUSE) 上面的这一组宏用于 check/set/clear 当前 chunk 使用标志位,有当前 chunk 的使用标志 位存储在下一个 chunk 的size 的第
0 bit (P 状态位) , 所以首先要获得下一个 chunk 的地址, 然后 check/set/clear 下一个 chunk 的size 域的第
0 bit. /* check/set/clear inuse bits in known places */ #define inuse_bit_at_offset(p, s)\ (((mchunkptr)(((char*)(p)) + (s)))->
size &
PREV_INUSE) #define set_inuse_bit_at_offset(p, s)\ (((mchunkptr)(((char*)(p)) + (s)))->
size |= PREV_INUSE) #define clear_inuse_bit_at_offset(p, s)\ (((mchunkptr)(((char*)(p)) + (s)))->
size &
= ~(PREV_INUSE)) 上面的三个宏用于 check/set/clear 指定 chunk 的size 域中的使用标志位. /* Set size at head, without disturbing its use bit */ #define set_head_size(p, s) ((p)->
size = (((p)->
size &
SIZE_BITS) | (s))) /* Set size/use field */ #define set_head(p, s) ((p)->
size = (s)) /* Set size at footer (only when chunk is not in use) */ #define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->
prev_size = (s)) 宏set_head_size(p, s)用于设置当前 chunk p 的size 域并保留 size 域的控制信息.宏set_head(p, s) 用于设置当前 chunk p 的size 域并忽略已有的 size 域控制信息.宏set_foot(p, s)用于设置当前 chunk p 的下一个 chunk 的prev_size 为s, s 为当前 chunk 的size, 只有当 chunk p 为空闲时才能使用这个宏,当前 chunk 的foot 的内存空间存在于下一个 chunk,即下一个 chunk 的prev_size.