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

C 語言動態記憶體管理:malloc/free 實戰與結構體動態分配詳解

     編輯:關於C語言

動態記憶體分配核心概念

C 語言透過 <stdlib.h> 提供的 malloc()、calloc()、realloc()、free() 四大函數實現執行期記憶體管理。動態分配的記憶體位於堆區,生命週期由程式設計師手動控制,靈活性高但需嚴防記憶體洩漏與懸空指標。

基本型別陣列動態分配

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int n;
    printf("請輸入陣列大小: ");
    scanf("%d", &n);
    
    // 1. 分配 n 個 int 的記憶體空間
    int *p = (int *)malloc(n * sizeof(int));
    if (p == NULL) {
        fprintf(stderr, "記憶體分配失敗\n");
        return 1;
    }
    
    // 2. 使用陣列
    for (int i = 0; i < n; i++) {
        p[i] = i * i;  // 指標即陣列名,支援下標存取
    }
    
    for (int i = 0; i < n; i++) {
        printf("%d ", p[i]);
    }
    putchar('\n');
    
    // 3. 釋放記憶體(關鍵步驟!)
    free(p);
    p = NULL;  // 防止懸空指標
    
    return 0;
}

關鍵點提醒

  • 型別轉換: malloc 回傳 void*,C 語言可隱性轉換,C++ 需顯性轉型
  • 錯誤檢查: 永遠檢查回傳值是否為 NULL
  • 配對釋放: 每個 malloc 必須對應一個 free
  • 歸零指標: free 後將指標設為 NULL,避免二次釋放或誤用

結構體動態分配實戰

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int num;
    char *name;      // 動態字串需額外分配
    char sex;
    float score;
} Student;

int main(void) {
    // 1. 分配結構體本身
    Student *ps = (Student *)malloc(sizeof(Student));
    if (ps == NULL) return 1;
    
    // 2. 為字串成員分配記憶體
    ps->name = (char *)malloc(20 * sizeof(char));
    if (ps->name == NULL) {
        free(ps);
        return 1;
    }
    
    // 3. 賦值
    ps->num = 102;
    strcpy(ps->name, "Zhang Ping");
    ps->sex = 'M';
    ps->score = 62.5f;
    
    // 4. 使用
    printf("Number=%d\nName=%s\n", ps->num, ps->name);
    printf("Sex=%c\nScore=%.1f\n", ps->sex, ps->score);
    
    // 5. 逆序釋放:先釋放內嵌指標,再釋放結構體
    free(ps->name);
    free(ps);
    ps = NULL;
    
    return 0;
}

結構體動態分配陷阱

錯誤寫法問題正確做法
ps->name = "Zhang Ping";指向字串常數區,不可修改,釋放時會崩潰分配記憶體後用 strcpy 複製
只 free(ps)內嵌 name 記憶體洩漏先 free(ps->name) 再 free(ps)
未檢查 malloc 回傳值分配失敗時解參考導致崩潰永遠檢查 NULL

進階:動態二維陣列與彈性陣列成員

方法一:指標陣列(不連續記憶體)

int **matrix = (int **)malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++) {
    matrix[i] = (int *)malloc(cols * sizeof(int));
}
// 釋放時逐行 free,最後 free(matrix)

方法二:連續記憶體塊(快取友善)

int *matrix = (int *)malloc(rows * cols * sizeof(int));
// 存取:matrix[i * cols + j]
free(matrix);  // 一次釋放

C99 彈性陣列成員

typedef struct {
    int len;
    int data[];  // 不定長陣列,必須是結構體最後一個成員
} FlexArray;

FlexArray *arr = malloc(sizeof(FlexArray) + n * sizeof(int));
arr->len = n;
// 釋放:free(arr) 一次搞定

常見錯誤與除錯技巧

  • 重複釋放: 導致 heap corruption,啟用 MALLOC_CHECK_ 環境變數偵測
  • 越界寫入: 破壞記憶體管理元資料,使用 Valgrind/AddressSanitizer 偵測
  • 記憶體洩漏: 程式長期運行耗盡記憶體,定期用工具檢查
  • 使用已釋放記憶體: 設定 p = NULL 後再次解參考會立即崩潰(好事),便於定位

總結

動態記憶體管理是 C 語言核心能力。遵循「誰分配誰釋放、分配即檢查、釋放即歸零」三原則,善用工具輔助除錯,即可安全發揮堆區記憶體的最大靈活性。

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