區域變數儲存在堆疊,函數返回即釋放。需跨函數生命週期或大小執行期決定的資料,必須使用堆記憶體。malloc/free 是 C 語言手動管理堆記憶體的核心組合。
| 函數 | 原型 | 說明 |
|---|---|---|
| malloc | void *malloc(size_t size) | 分配 size 位元組,回傳起始位址 (void*),失敗回傳 NULL |
| free | void free(void *ptr) | 釋放 malloc 分配的記憶體,ptr 必須為 malloc 返回值或 NULL |
| calloc | void *calloc(size_t n, size_t size) | 分配 n 個 size 位元組並歸零 |
| realloc | void *realloc(void *ptr, size_t size) | 調整已分配區塊大小,可能移動位址 |
#include <stdlib.h>
Folder *f = malloc(sizeof(Folder)); // 分配單個節點
if (!f) { /* 處理分配失敗 */ }
f->level = 1;
f->filename = "first";
f->child = NULL;
// 使用完畢必須釋放
free(f);
f = NULL; // 防止野指標
malloc(sizeof(Folder)) 而非 sizeof(f)(後者為指標大小)malloc 對應一個 free,否則記憶體洩漏free(ptr); ptr = NULL; 避免二次釋放/使用已釋放記憶體free(&local_var)、free(ptr+1) 皆錯誤// 錯誤 1:釋放後繼續使用
free(f);
printf("%s", f->filename); // Use-after-free
// 錯誤 2:二次釋放
free(f);
free(f); // Double free,破壞堆管理結構
// 錯誤 3:釋放堆疊記憶體
Folder local;
free(&local); // 未定義行為
// 錯誤 4:忘記釋放(記憶體洩漏)
while (1) {
Node *n = malloc(sizeof(Node));
// 缺少 free(n)
}
valgrind --leak-check=full ./prog 檢測洩漏、越界、使用已釋放記憶體-fsanitize=address,運行時即時報錯mtrace() 記錄分配/釋放日誌void *safe_malloc(size_t size) {
void *p = malloc(size);
if (!p) {
fprintf(stderr, "FATAL: malloc(%zu) failed\n", size);
exit(EXIT_FAILURE);
}
return p;
}
void safe_free(void **ptr) {
if (ptr && *ptr) {
free(*ptr);
*ptr = NULL;
}
}
// 使用
Folder *f = safe_malloc(sizeof(Folder));
// ...
safe_free((void**)&f);
封裝後統一錯誤處理、自動置 NULL、防止二次釋放,大幅降低記憶體錯誤率。