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

C 語言指標七大易錯陷阱與避坑指南:記憶體洩漏、污染、野指標、越界、疊加、棧區逃逸、重複釋放

     編輯:關於C語言

指標威力大,責任也大

指標賦予 C 語言直接記憶體操作能力,但也引入一類難以重現、難以定位的錯誤。以下整理七大高發陷阱與防禦模式。

1. 記憶體洩漏

成因:malloc/calloc/realloc 分配堆積記憶體,無對應 free。
防禦:
• 分配與釋放配對,所有權清晰 (誰分配誰釋放)。
• 使用 valgrind --leak-check=full 例行檢測。
• 考慮 RAII 風格封裝或智慧指標 (C++)。

2. 記憶體污染

成因:非法寫入 (越界、使用後釋放、未初始化指標) 未即時崩潰,破壞鄰近資料結構,後續無關處崩潰。
典型案例:結構體柔性陣列成員寫入超出分配大小,後續新增成員時編譯器報錯「無法定義變數」,實為前序污染。
防禦:
• 開啟 -fsanitize=address (ASan) 編譯測試。
• 結構體末尾加 金絲雀值 定期校驗。
• 嚴格檢查緩衝區邊界。

3. 空/非法字串指標判斷錯誤

錯誤:if (*str == '\0') 先解參考再判斷 → 若 str == NULL 直接崩潰。
正確:if (str == NULL || *str == '\0') 先判斷指標值,再解參考。

4. 指標越界

案例:char str[3] = "abc"; // 實際需 4 字元含 '\0'
防禦:
• 字串緩衝區預留 +1 空間給結尾 NUL。
• 使用 strncpy/snprintf 限制長度。
• 靜態分析工具 (cppcheck, clang-tidy) 捕獲編譯期可見越界。

5. 指標疊加導致邏輯錯誤

現象:char *p = "sdfg"; p++; printf("%s", p); // 輸出 "dfg"
連續 p++ 移動指標,最終指向 '\0' 或越界。
防禦:
• 保留原始指標 char *start = p; 供後續釋放/重用。
• 使用索引 p[i] 而非移動指標。

6. 棧區區域變數位址逃逸

錯誤:

char *get_str() {
    char str[] = "abcd"; // 棧上
    return str;          // 返回棧位址 → 野指標
}
正確:
• 靜態儲存:static char str[] = ... (線程不安全)。
• 呼叫者提供緩衝區:void get_str(char *buf, size_t len)。
• 動態分配:return strdup("abcd"); (呼叫者負責 free)。

7. 同一記憶體重複釋放

錯誤:

free(p);
if (p != NULL) free(p); // p 未置 NULL,二次 free → 未定義行為
正確模式:
if (p) { free(p); p = NULL; }
原則:free 後立即置 NULL,杜絕野指標與重複釋放。

總結:指標防禦清單

陷阱核心對策
洩漏所有權明確 + valgrind/ASan 例行檢測
污染ASan + 金絲雀值 + 邊界檢查
空指標解參考先判 NULL 再解參考
越界預留 NUL + 安全函式 + 靜態分析
疊加保留基址 / 改用索引
棧逃逸呼叫者分配 / 靜態 / 動態分配
重複釋放free 後立即 p = NULL
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved