内存分配器 dlmalloc 2.8.3 源码浅析
G#8%&#HI>>/%:#)??
G#8%&#HJ>>/%:#)??
G#8%&#I1K>HI?
G#8%&#I1K>HJ?
G#8%&# %&!/#>(?>>(?3F4#LI1K?
G#8%&#(%&!/#>(?>>(?3F4#LI1K?
(.#;8) 字段虽然在当前 4!&+ 块结构体内,记录的却是前一个邻接 4!&+ 块的信息
(有特例存在,马上会讲到),这样做的好处就是我们通过本块 4!&+ 结构体就可以直接
获取到前一 4!&+ 块的信息,从而方便做进一步的处理操作。相对的,当前 4!&+ 块的 8)
信息就存在于下一个邻接 4!&+ 块的结构体内。
字段 (.#;8) 记录的什么信息呢?有两种情况:)如果前一个邻接 4!&+ 块空闲,
那么当前 4!&+ 块结构体内的 (.#;8) 字段记录的是前一个邻接 4!&+ 块的大小。此时我
们可以利用如下代码:
G#8%&#(.#; 4!&+>(?>> 4!&+().?>>> 4.=?>(??3>>(?3F(.#;8)???
来获得前一个邻接 4!&+ 块的 4!&+ 结构体指针。插播一句,利用字段 4# 可以获
取下一个邻接 4!&+ 块的 4!&+ 结构体指针,如下:
#dene next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head &
~INUSE_BITS)))
)如果前一个邻接 4!&+ 块正在被使用中,那么当前 4!&+ 块结构体内的 (.#;8) 字
段记录的是它们所在的结构体 /))# 变量信息,具体来说是这样:
/* Set foot of inuse chunk to be xor of mstate and seed */
#dene mark_inuse_foot(M,p,s)\
(((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^
mparams.magic))
结构体 /))# 在后面几节会讲到,总之记录结构体 /))# 变量信息用于做
额外的安全检测,因此同时也会额外降低 性能,所以只有当开启了这一功能时
(即定义了 宏)才有这种情况,默认是不开启的。
和字段 4# 一样, 也利用了 (.#;8) 字段的最末 2%) 位(第 * 位)来记录该
4!&+ 块是如何分配的,当该 4!&+ 块是直接通过函数 (>?从系统获取内存分配的时,
该 2%) 被置为 。虽然该 4!&+ 块前没有邻接实际的 4!&+ 块(因为它是通过函数 (>?独
立分配的),但是此 (.#;8) 字段记录的大小也不一定就是 *,因为 4!&+ 块需要对齐,
因此此 4!&+ 块的首地址不一定和 (>?返回的内存段首地址完全一致,未对齐的那部分
空间就伪装成一个 4!&+ 块,即该 4!&+ 块的 (.#;8) 字段记录这段未对齐部分内存的大
小,这样再实际调用函数 !&(>?释放该 4!&+ 块时能获取到正确的映射地址。关于这段
叙述的具体代码请参考函数 ( >?。
指针 8、2+ 只有当该 4!&+ 块空闲时才存在,其作用是用于将对应的空闲 4!&+ 块加
入到空闲 4!&+ 块链表中统一管理,而如果该 4!&+ 块被分配给应用程序使用,那么这两
我心永恒爱无止境
评论2
最新资源