首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言動態記憶體管理:malloc/free 實戰與記憶體洩漏防範

     編輯:關於C語言

C 語言動態記憶體管理:malloc/free 實戰

區域變數儲存在堆疊,函數返回即釋放。需跨函數生命週期或大小執行期決定的資料,必須使用堆記憶體。malloc/free 是 C 語言手動管理堆記憶體的核心組合。

核心函數

函數原型說明
mallocvoid *malloc(size_t size)分配 size 位元組,回傳起始位址 (void*),失敗回傳 NULL
freevoid free(void *ptr)釋放 malloc 分配的記憶體,ptr 必須為 malloc 返回值或 NULL
callocvoid *calloc(size_t n, size_t size)分配 n 個 size 位元組並歸零
reallocvoid *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;  // 防止野指標

關鍵規則與陷阱

  1. sizeof 傳型別而非變數:malloc(sizeof(Folder)) 而非 sizeof(f)(後者為指標大小)
  2. 檢查 NULL:分配失敗回傳 NULL,解參考導致崩潰
  3. 成對使用:每個 malloc 對應一個 free,否則記憶體洩漏
  4. 釋放後置 NULL:free(ptr); ptr = NULL; 避免二次釋放/使用已釋放記憶體
  5. 釋放非 malloc 指標未定義: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:valgrind --leak-check=full ./prog 檢測洩漏、越界、使用已釋放記憶體
  • AddressSanitizer (ASan):編譯加 -fsanitize=address,運行時即時報錯
  • mtrace:Glibc 內建,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、防止二次釋放,大幅降低記憶體錯誤率。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved