Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學

深入解析 glibc malloc/free 核心實現機制

編輯:Linux 系統常見問題解答

核心數據結構:Chunk

C 標準庫在管理堆內存分配時,以 chunk 作為基本邏輯單元。每個 chunk 在內存中呈現為一個結構體,包含大小、指針等元數據:

struct malloc_chunk {  size_t prev_size;  // 前一個 chunk 的大小(僅在前一個 chunk 空閒時有效)  size_t size;       // 當前 chunk 大小(低 3 位用作標誌位)  struct malloc_chunk* fd;         // 雙向鏈表前向指針(空閒時)  struct malloc_chunk* bk;         // 雙向鏈表後向指針(空閒時)  struct malloc_chunk* fd_nextsize; // 大塊內存鏈表指針  struct malloc_chunk* bk_nextsize; // 大塊內存鏈表指針 };

狀態切換邏輯:當 chunk 處於空閒狀態時,fd 和 bk 構成雙向鏈表,便於快速分配與合併;一旦被分配,size 之後的空間即成為用戶數據區,fd/bk 失去原意。size 字段記錄用戶實際申請的大小,prev_size 則用於快速定位相鄰 chunk,實現 O(1) 的合併操作。

關鍵宏與地址轉換

glibc 定義了一系列宏簡化 chunk 與用戶指針互轉(假設 SIZE_SZ = sizeof(size_t)):

  • chunk2mem(p) = (void*)((char*)(p) + 2*SIZE_SZ):從 chunk 頭部跳過兩個 size_t 得到用戶指針。
  • mem2chunk(mem) = (mchunkptr)((char*)(mem) - 2*SIZE_SZ):反向操作。

由於 chunk 按 8 字節對齊,size 低 3 位恆為 0,被用作標誌位:

  • PREV_INUSE (0x1):前一個 chunk 是否在用。
  • IS_MMAPPED (0x2):是否由 mmap 分配。

常用導航宏:

#define next_chunk(p) ((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))#define prev_chunk(p) ((mchunkptr)(((char*)(p)) - ((p)->prev_size)))#define inuse(p) ((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)

malloc_state:分配器全局狀態

分配器維護一個 malloc_state 結構(主 arena 為全局變量 main_arena),核心字段包括:

  • fastbins[NFASTBINS]:小塊快速緩存(單向鏈表,LIFO)。
  • top:頂塊指針,剩餘最大連續內存區。
  • bins[NBINS*2-2]:常規 bins(雙向循環鏈表),按大小分類,支持 best-fit。
  • binmap:位圖加速非空 bin 查找。

分配策略分級:

  1. < 64B:優先從 fastbin 分配(無合併,極快)。
  2. 64B ~ 512B:small bins,FIFO,支持合併。
  3. > 512B:large bins,best-fit,引入 fd_nextsize/bk_nextsize 加速大小查找。

malloc 核心流程(_int_malloc)

  1. 對齊計算:request2size(req) 將用戶請求轉為含元數據的 chunk 大小,最小 MINSIZE(32 位機 16B,64 位機 32B),確保至少容納 prev_size, size, fd, bk 四字段。
  2. Fastbin 命中:索引 fastbin_index(nb) = (nb>>3) - 2,直接從對應單向鏈表頭取塊,驗證大小一致性後返回。
  3. Small Bin 分配:遍歷對應 bin 鏈表,取首塊,若餘量足夠則分割,否則整塊分配。
  4. Large Bin / Unsorted Bin:best-fit 搜索,必要時分割並將餘塊放回 unsorted bin。
  5. Top Chunk 分割:以上均失敗則從 top chunk 切分;不足則調用 sysmalloc 向系統申請(brk 或 mmap)。

free 核心流程(_int_free)

  1. 檢查雙重釋放、非法指針。
  2. 若相鄰前塊空閒,向後合併(修改前塊 size,摘除前塊鏈表)。
  3. 若相鄰後塊空閒(非 top chunk),向前合併(摘除後塊鏈表)。
  4. 合併後放入對應 bin 或 unsorted bin;若觸及 top chunk 邊界則直接合併入 top。
  5. 大塊釋放時可能觸發 malloc_trim 歸還內存給 OS。

安全機制與調試

  • 雙重釋放檢測:fastbin 入鏈前驗證 fastbin_index(chunksize(victim)) == idx。
  • 堆一致性檢查:check_remalloced_chunk、malloc_printerr。
  • 擾亂字節:perturb_byte 可選填充新分配/釋放內存,暴露未初始化讀寫。

理解上述機制有助於診斷堆損壞、優化內存碎片、編寫高性能分配器或進行二進制漏洞利用分析。

Copyright © Windows教程網 All Rights Reserved