首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言 free() 釋放內存後指針非 NULL:值傳遞導致原指針未置空與野指針風險

     編輯:程式設計綜合問答

錯誤代碼分析


void testFree(char *par) {
    void*free(par); // 語法錯誤:void* 是類型聲明,非調用
    par = NULL;     // 只修改副本,原指針不變
}

int main() {
    char *str = malloc(100);
    testFree(str);
    printf("%s", str); // 未崩潰但屬未定義行為:訪問已釋放內存 (野指針)
}

三大問題

  1. 語法錯誤:`void*free(par)` 被解析為聲明函數指針 `free`,而非調用 `free(par)`。正確寫法 `free(par);`。
  2. 值傳遞無法置空原指針:函數參數 `par` 是指針副本,`par = NULL` 僅修改副本。調用者 `str` 仍指向已釋放地址 → **野指針**。
  3. 釋放後繼續使用:`printf("%s", str)` 訪問自由內存,可能輸出殘留數據、崩潰、或沉默破壞堆元數據。

正確釋放並置空模式

方案一:二級指針 (C 風格)


void safeFree(void **ptr) {
    if (ptr && *ptr) {
        free(*ptr);
        *ptr = NULL; // 修改原指針值
    }
}

// 調用
safeFree((void**)&str); // 需強轉,因 void** 不能隱式轉換 char**

方案一修正:宏封裝 (推薦 C 通用)


#define SAFE_FREE(p) do { if (p) { free(p); (p) = NULL; } } while(0)

SAFE_FREE(str); // 直接使用,無類型轉換問題

方案二:C++ 智能指針 (現代 C++)


#include 
std::unique_ptr str(new char[100]); // 自動釋放,無需手動 free
// 或
std::vector buf(100); // 容器管理內存

內存釋放後驗證

  • **工具檢測**:Valgrind (`--leak-check=full`)、AddressSanitizer (`-fsanitize=address`)、Visual Studio CRT 调试堆 (`_CrtDumpMemoryLeaks`)。
  • **規範**:分配與釋放配對、釋放即置空、避免多重釋放、避免釋放後訪問。

本例輸出 "abc" 原因

釋放後內存未被覆寫,殘留數據偶然可讀,**純屬巧合**,屬未定義行為,不同編譯器/優化等級/運行環境結果不同。**切勿依賴此行為**。

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