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

C 指針常見錯誤總結(六):安全隱患、野指針、記憶體洩漏與最佳防禦實踐

     編輯:關於C語言

C 指針常見錯誤總結(六):安全隱患、野指針、記憶體洩漏與最佳防禦實踐

指針是 C 語言最強大也最危隐的特性。本文歸納六大類高發錯誤場景,提供代碼反例與防禦模式,助你構建記憶體安全的程式。

一、聲明與初始化陷阱

1. 宏定義指針類型的陷阱

#define PINT int*
PINT ptr1, ptr2; // 實為 int* ptr1, ptr2;  ptr2 是 int 而非指針!

修正:用 typedef int* PINT;,則 PINT ptr1, ptr2; 皆為指針。

2. 未初始化指針(野指針)

區域指針未賦值指向隨機地址,解參考導致未定義行為。

  • 鐵律:宣告即初始化 int *p = NULL;
  • 斷言檢查:assert(p != NULL); 捕獲空指針解參考。
  • 工具輔助:Valgrind、AddressSanitizer 靜態/動態分析。

二、緩衝區溢出與邊界越界

常見原因

  • 陣列下標未檢查
  • 指針算術運算越界
  • 使用 gets()、strcpy()、strcat() 等不安全函數

防禦模式

// 安全版字串複製
void safe_copy(char *dest, size_t dest_size, const char *src) {
    size_t len = strlen(src);
    if (len >= dest_size) len = dest_size - 1;
    memcpy(dest, src, len);
    dest[len] = '\0';
}

三、動態記憶體管理錯誤

1. malloc 返回值未檢查

int *p = malloc(n * sizeof(int));
if (!p) { /* 處理失敗 */ return; }

2. 迷途指針

free(p) 後繼續使用 p,指向已釋放記憶體。

  • 釋放後立即置空:free(p); p = NULL;
  • 釋放前清理敏感資料:memset(p, 0, size); free(p);

3. 重複釋放

對同一指針多次 free() 導致堆破壞。置空策略可有效預防。

四、sizeof 誤用與類型不匹配

陷阱:指針退化導致 sizeof 失效

void func(int arr[]) {  // 實為 int* arr
    printf("%zu\n", sizeof(arr)); // 輸出指針大小(4/8),非陣列大小!
}

對策:陣列作參數時,必須同步傳遞長度。

五、字串安全與結構體指針算術

  • 字串操作務必確保目標緩衝區足夠大,預留 \0 空間。
  • 指針算術僅適用於陣列(連續記憶體),結構體因填充/對齊導致字段非連續,不可用指針算術遍歷字段。

六、函數指針與總結檢查清單

指針錯誤總結圖

核心防禦清單

  1. 宣告即初始化為 NULL
  2. 解參考前斷言非空
  3. malloc 必檢查返回值
  4. 陣列/緩衝區操作帶長度參數
  5. 釋放後立即置空
  6. 用 strncpy/snprintf 替代不安全函數
  7. 啟用編譯器警告(-Wall -Wextra)與 sanitizers

指針錯誤多屬「海森堡 Bug」——難以復現、後果嚴重。建立防禦性編程習慣,善用工具鏈,是 C 開發者的必修課。

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