C 程序員每天與 malloc/free/calloc/realloc 打交道,卻鮮少探究其內部實現。本文以 glibc 2.3.5 (32 位 Linux) 為例,剖析內存管理器的設計目標、核心算法與關鍵數據結構。
設計優秀的分配器需在多目標間權衡:
brk/mmap)不存在「最好」的算法,只有適合特定場景的權衡。
| 請求大小 | 分配策略 |
|---|---|
| ≤ 64 字節 | Pool 算法(快速池分配) |
| 64 ~ 512 字節 | Best-fit 與 Pool 混合 |
| ≥ 512 字節 | Best-fit 算法 |
| ≥ 128 KB | 直接 mmap 向 OS 申請 |
brk(void *end_data_segment):擴展堆頂地址sbrk(ptrdiff_t increment):按增量擴展堆mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset):大塊內存映射,繞過堆free(NULL):標準要求無操作,不崩潰malloc(0):返回最小合法內存塊(非 NULL)struct malloc_chunk {
size_t prev_size; // 前一塊大小(前塊空閒時有效)
size_t size; // 當前塊大小 | 低 2 位標志:M(mmap) P(prev_inuse)
// 用戶數據從這裡開始
};
利用對齊導致的低位為 0 存儲標志位,極其巧妙。
struct malloc_chunk {
size_t prev_size;
size_t size;
struct malloc_chunk *fd; // 前向指針
struct malloc_chunk *bk; // 後向指針
// 剩餘空間
};
最小塊 16 字節:兩個 size_t + 兩個指針。空閒時強制轉型為鏈表節點,無需額外元數據空間。


calloc:利用對齊特性,按 4 字節批量清零,比手動 malloc+memset 快realloc:原地擴展避免拷貝;縮小直接修改大小;比 malloc+copy+free 高效strdup/strndup:常用字符串複製,可用 malloc 模擬無性能損失glibc malloc 是工業級內存分配器的典範,通過分級策略、巧妙數據結構、線程局部緩存等技術,在通用性與性能間達到優秀平衡。理解其原理,有助於排查內存碎片、洩露、性能抖動等疑難雜癥,也為編寫自定義分配器奠定基礎。