free(釋放)
你從 malloc、calloc 或 realloc 取得的每一塊都是借來的,不是永久擁有。free 就是你把區塊還給配置器、讓記憶體能被下一個請求重用的方式。用先前的比喻來說,就是歸還寄物櫃鑰匙。若你從不還鑰匙,整間寄物櫃就會被占滿,別人都拿不到——這就是記憶體洩漏。
精確地說:free(p) 接受一個由先前配置回傳的指標 p(或 NULL,它會安全地忽略),並把該區塊重新標示為可用。free 返回後,這塊區塊不再屬於你;配置器可能把同一塊記憶體交給未來的某次 malloc。有兩件事是 free 不做的,常讓初學者吃驚。第一,free 不會改變 p 的值——你的變數仍持有舊位址,而它現在指向你已不再擁有的記憶體。這樣的指標是懸置指標,使用它是未定義行為;安全的習慣是在釋放後立刻寫 p = NULL。第二,free 不會清除位元組——舊內容可能還在,所以懸置讀取有時會僥倖看似正常,這讓錯誤變得時有時無、難以尋找。
這裡有一條嚴格的契約。你必須把配置器回傳的那個確切指標傳給 free——不是指向區塊中間的指標、不是堆疊位址、不是字串字面值。你必須對每一塊剛好釋放一次:把同一塊釋放兩次就是重複釋放,會破壞配置器的記帳資料,且是未定義行為。呼叫 free(NULL) 是明確被允許的,且什麼都不做,這就是為什麼你可以安全地釋放一個已設為 NULL 的指標。讓每次成功的配置都對應剛好一次 free,大多數堆積錯誤就會消失。
char *s = malloc(64); /* ... 使用 s ... */ free(s); s = NULL; /* 拆除懸置指標;之後 free(NULL) 也無害 */
free 歸還區塊;之後把指標設為 NULL 可防止意外的釋放後使用與重複釋放。
free 不會清零記憶體,也不會把你的指標設為 NULL。釋放後指標仍是懸置的,直到你自己把它設為 NULL。