Obstack = Object Stack。GNU C 庫擴展,屬於Region-based memory management(基於區域的內存管理)。將相關對象集中在一個邏輯棧中,支持:
free。malloc/free 碎片化,提高局部性。本質:內存池管理員。預先分配大塊 chunk(默認 4KB),在池中按棧式分配對象;池滿自動申請新 chunk。對象間可能需填充對齊(以空間換時間)。
#include <obstack.h> struct obstack; // 不透明結構,僅記錄狀態與 chunk 鏈表指針 // 必須由用戶定義的宏(指向分配/釋放函數) #define obstack_chunk_alloc malloc #define obstack_chunk_free free // 可選:分配失敗處理器 void (*obstack_alloc_failed_handler)(void); // 初始化 int obstack_init(struct obstack *ptr); // 總返回 1,失敗調用 handler // 示例 static struct obstack myobstack; obstack_init(&myobstack); // 或動態 struct obstack *p = malloc(sizeof(struct obstack)); obstack_init(p);
// 宏展開為左值,可直接賦值 if (obstack_chunk_size(ptr) < NEW_SIZE) obstack_chunk_size(ptr) = NEW_SIZE;
增大 chunk 減少系統調用,提高效率;減小無益處。
void *obstack_alloc(struct obstack *ptr, int size); // 不初始化 void *obstack_copy(struct obstack *ptr, void *addr, int size); // 從 addr 複製 size 字節初始化 void *obstack_copy0(struct obstack *ptr, void *addr, int size); // 複製並追加 \0,適合字符串
釋放:
void obstack_free(struct obstack *ptr, void *obj);
obj == NULL:釋放所有對象,保留 Obstack 結構(chunk 歸還)。obj != NULL:釋放 obj 及其之後分配的所有對象(棧頂回縮)。obstack_free(ptr, first_obj)。利用 chunk 連續空間特性,支持增量構建(如動態字符串、可變長數組)。
void obstack_blank(struct obstack *ptr, int size); // 預留未初始化空間 void obstack_grow(struct obstack *ptr, void *data, int size); // 追加數據 void obstack_grow0(struct obstack *ptr, void *data, int size); // 追加並加 \0 void obstack_1grow(struct obstack *ptr, char c); // 追加單字符 void obstack_ptr_grow(struct obstack *ptr, void *data); // 追加指針 void obstack_int_grow(struct obstack *ptr, int data); // 追加 int
關鍵:構建完成必須調用 void *obstack_finish(struct obstack *ptr) 獲取最終地址並固化對象。
obstack_object_size(ptr) 返回當前構建大小(僅 finish 前有效)。
取消構建:obstack_free(ptr, obstack_finish(ptr))。
在確信 chunk 剩餘空間足夠時,使用 _fast 後綴版本(如 obstack_1grow_fast),跳過邊界檢查,極致性能。
輔助:int obstack_room(struct obstack *ptr) 返回當前 chunk 可安全寫入字節數。
void *obstack_base(struct obstack *ptr); // 當前構建對象起始地址(假定,可能換 chunk) void *obstack_next_free(struct obstack *ptr); // 當前 chunk 首個空閒字節地址 int obstack_object_size(struct obstack *ptr); // 等價於 next_free - base
int obstack_alignment_mask(struct obstack *ptr); // 掩碼,值為 2^n-1,地址對齊到 2^n // 修改後下次分配生效;growing object 立即生效(finish 後可見)
文檔來源:原文鏈接