典型 C 程序在虛擬內存中的分段(由高到低):
mmap 映射文件malloc/free 管理區域void *sbrk(intptr_t increment); // 移動 program break,擴展/縮減堆 int brk(void *addr); // 直接設置 program break
特點:
sbrk(0) 返回當前 program break 位置(堆頂)。munmap 歸還內核;否則僅移動 break,物理頁保留進程佔用。每塊分配內存前置元數據:至少包含塊大小、標志位(空閒/在用)、前向/後向指針(空閒鏈表)。
malloc 返回的是用戶數據區起始地址(元數據之後)。
free 時檢查相鄰塊是否空閒,向前/向後合併減少碎片。char *p = malloc(10); p[10] = 0; // 越界 1 字節,恰好覆蓋下一塊的 size 字段 free(p); // free 讀取錯誤 size → 破壞空閒鏈表 → 後續 malloc 崩潰
對策:紅區、Canary、AddressSanitizer、電檢工具。
| 函數 | 行為 | 典型場景 |
|---|---|---|
calloc(n, size) | 分配 n*size 並置零 | 需要零初始化的數組/結構體 |
realloc(ptr, size) | 調整大小;可能移動內存(返回新地址) | 動態數組擴容 |
aligned_alloc(align, size) | 返回 align 對齊地址 (C11) | SIMD、硬件 DMA、緩存行對齊 |
alloca(size) | 棧上分配,函數返回自動釋放 | 小臨時緩衝、setjmp/longjmp 避免洩漏 |
注意:realloc 可能移動內存,舊指針失效;alloca 過大導致棧溢出,慎用於循環/遞歸。
NULL。malloc/free,避免雙重釋放、洩漏、使用後釋放。struct { size_t len; char data[]; }。mmap(glibc 閾值可調 M_MMAP_THRESHOLD)。jemalloc/tcmalloc/mimalloc 替換默認分配器。內存管理是 C 程序穩定性的命門,理解分配器內部原理,才能寫出健壯、高效的系統級代碼。