C 語言提供多種記憶體分配方式,各有適用場景與生命週期管理差異。本文將 malloc、calloc、realloc、alloca 四大函式置於同一維度對比,助你快速選型。
| 函式 | 分配區域 | 初始化 | 大小調整 | 釋放方式 | 典型用途 |
|---|---|---|---|---|---|
malloc | 堆區 | 不初始化(隨機值) | 不可調整 | 手動 free() | 通用動態分配、結構體、單一大塊緩衝區 |
calloc | 堆區 | 全部位元歸零 | 不可調整 | 手動 free() | 陣列分配、結構體陣列、需零值初始化場景 |
realloc | 堆區 | 保留舊資料,新增部分不初始化 | 可擴大/縮小(位址可能遷移) | 手動 free() | 動態陣列、緩衝區增長、字串拼接 |
alloca | 棧區 | 不初始化 | 不可調整 | 自動(函式返回時釋放) | 臨時小型緩衡區、setjmp/longjmp 跨跳轉保持資料 |
size 位元組連續虛擬記憶體void*,需強制轉型(C++ 必須)free() 釋放,否則造成記憶體洩漏nmemb * size 位元組malloc + memset(ptr, 0, total) 但更高效(作業系統層面零頁映射)nmemb 為元素個數,size 為單元大小,防止整數溢位誤判free() 釋放ptr 可為 NULL(等同 malloc)或有效堆區位址ptr = realloc(ptr, new_size);size 位元組,零系統調用開銷free,嚴禁 在循環或大尺寸(> 數 KB)使用,易導致棧溢位_allocasetjmp/longjmp 需在長跳轉後保持有效的臨時緩衝區需要跨函式生命週期?
├─ 是 → 堆區分配
│ ├─ 已知固定大小 → malloc / calloc(需零值)
│ └─ 需動態增減 → realloc
└─ 否 → 僅當前函式使用
├─ 大小固定且較小 → 區域變數/靜態陣列(最佳)
├─ 大小動態但極小 → alloca(謹慎)
└─ 其他 → malloc + 手動 free(保險)
malloc 後未檢查 NULL 直接解引用realloc 直接覆寫原指標,導致遷移時舊指標懸空alloca 在循環或大塊分配,炸棧NULL:free(p); p = NULL;calloc 確保指標成員為 NULLvalgrind --leak-check=full 檢測洩漏掌握四大函式的區域、生命週期、初始化語意,即能在效能與安全性間找到平衡。現代 C++ 建議優先使用 std::vector、std::unique_ptr、std::make_unique 等 RAII 容器/智慧指標,將記憶體管理交給編譯器。