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

C 語言記憶體與指標進階:參數傳遞陷阱、動態記憶體回傳與野指標根治

     編輯:關於C語言

一、 指標參數傳遞記憶體的核心誤區

若函式參數是指標,在函式內對該指標重新分配記憶體 (malloc),無法影響呼叫端的原始指標。

錯誤示範

void GetMemory(char *p, int num) {
    p = (char*)malloc(sizeof(char) * num); // 修改區域副本 _p
}
void Test() {
    char *str = NULL;
    GetMemory(str, 100); // str 仍為 NULL
    strcpy(str, "hello"); // 崩潰
}

原因:編譯器建立參數副本 _p,函式內修改 _p 指向,原 p (即 str) 不變。且每次調用洩漏一塊記憶體。

正確方案 1:傳遞指標的指標 (雙重指標)

void GetMemory2(char **p, int num) {
    *p = (char*)malloc(sizeof(char) * num); // 解引用修改原指標值
}
void Test2() {
    char *str = NULL;
    GetMemory2(&str, 100); // 傳入 str 位址
    strcpy(str, "hello");
    free(str);
}

正確方案 2:函式回傳值 (更簡潔)

char *GetMemory3(int num) {
    char *p = (char*)malloc(sizeof(char) * num);
    return p;
}
void Test3() {
    char *str = GetMemory3(100);
    strcpy(str, "hello");
    free(str);
}

二、 回傳指標的致命陷阱:勿回傳堆疊記憶體位址

char *GetString() {
    char p[] = "hello world"; // 區域陣列在堆疊
    return p; // 警告:回傳區域變數位址
}
void Test4() {
    char *str = GetString(); // str 指向已銷毀記憶體,內容為垃圾值
}

修正:回傳靜態/常數區或動態記憶體位址

char *GetString2() {
    char *p = "hello world"; // 指向常數區 (或用 static/malloc)
    return p; // 安全
}

三、 記憶體錯誤五大鐵律 (複習強化)

  1. 分配前檢查:assert(p != NULL) 或 if(p==NULL)。
  2. 必初始化:陣列、動態記憶體用前賦值,勿信賴預設 0。
  3. 防越界:迴圈邊界嚴謹,警惕「多 1/少 1」。
  4. 配對釋放:malloc/free、new/delete 次數嚴格對等。
  5. 釋放即置 NULL:free(p); p = NULL; 杜絕野指標。

四、 指標與陣列補充:函式參數退化

陣列作參數時退化為指標,sizeof 失效。若需在函式內得知陣列大小,必須額外傳遞長度參數,或使用結構體包裹。

總結

指標參數傳遞記憶體的本質是「值傳遞指標值」。要修改呼叫端指標指向,必須傳遞指標的位址 (雙重指標) 或利用回傳值。堅決杜絕回傳堆疊位址,嚴守釋放即置 NULL,是 C 程式設計師的職業素養。

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