在 C 語言程序開發中,動態內存管理是一項核心技能。與靜態內存分配不同,動態內存允許程序在運行時根據實際需求申請和釋放內存空間,極大地提高了內存使用效率。然而,這種靈活性也帶來了管理複雜性——特別是在大型項目中,動態內存的申請與釋放若處理不當,極易導致內存洩漏、野指針等難以排查的問題,甚至成為服務器定期重啟的根本原因。
#include <stdlib.h>
void *malloc(size_t size);
malloc 根據指定的位元組數 size 分配一塊未初始化的內存區塊。成功時返回指向該區塊的指針,失敗返回 NULL。分配的內存內容是不確定的(垃圾值)。
void *calloc(size_t nmemb, size_t size);
calloc 分配 nmemb 個大小為 size 的元素,總大小為 nmemb * size。與 malloc 最大的區別在於:calloc 會將分配的內存自動初始化為全零,適合需要清零初始化的場景(如結構體數組、字符串緩衝區)。
void *realloc(void *ptr, size_t size);
realloc 用於調整已分配內存塊的大小:
ptr 為原內存塊指針(可為 NULL,等同 malloc)size 為新大小(可大於或小於原大小;為 0 時等同 free)NULL(原塊不變)關鍵陷阱: 調用 realloc 後,必須用返回值更新指針,否則若發生移動,舊指針變為野指針,導致崩潰或數據損壞。
void free(void *ptr);
free 僅能釋放由 malloc/calloc/realloc 返回的指針。釋放後:
char *alloc_test() {
char *pchar = malloc(20);
strcpy(pchar, "hello alloc_test");
return pchar;
}
int main() {
char *p1 = alloc_test();
char *p2 = p1; // 兩個指針指向同一塊內存
printf("%s\n", p1);
printf("%s\n", p2);
free(p1); // 正確釋放
// free(p2); // 錯誤!重複釋放同一塊內存
return 0;
}
錯誤本質: p1 和 p2 共享同一內存塊,free(p1) 後內存已歸還系統,free(p2) 屬於二次釋放。同理,函數內部的 pchar 也不應再次釋放。
ptr = NULL;),避免野指針誤用valgrind、AddressSanitizer 等工具定期檢測洩漏掌握動態內存管理的精髓,不僅是記住 API,更是建立「內存所有權」與「生命週期」的工程思維——這正是 C 程序員進階的分水嶺。