free 與 CFRelease 的區別

根本停不下來發表於2018-08-10

如果我們使用 creat new copy 等函式,就會開闢一段堆空間,返回一個物件。

用一個指標指向這個物件:ptr = obj;,我們要釋放這塊物件的記憶體,就可以這樣做:free(ptr); ,這時在堆上的記憶體就已經被釋放了。但這還沒有完,雖然我們堆上的空間已經被釋放了,但是ptr裡面還是有值的,如果仍然在程式中使用ptr指標的話就會出現壞記憶體訪問的問題。正確的做法是在free之後,再清空指標:ptr = NULL;

如果上述步驟先執行的是ptr = NULL,那麼堆上的這塊記憶體將永遠不會被釋放!


在 OC 中建立的 CF 物件,記憶體是不被 ARC 所管理的。假設有一個 CF 物件 cfObj 和指標 cfPtr: cfPtr = cfObj;

當 cfObj 建立的時候會佔用堆上的一塊記憶體,記為堆空間1

cfObj 本質上是一個結構體,它裡面可能有其它的指標,它們都有可能會建立新的堆空間記為堆空間2~N

如果呼叫 free(cfPtr),那麼僅僅只會釋放堆空間1的記憶體,堆空間2~N將永遠不會被釋放。

如果使用 CFRelease(cfPtr),它會先釋放堆空間2~N,再釋放堆空間1。它們都會得到釋放。


還有一個問題

上面提到了使用 free 之後要將指標置為 NULL 才能將指標清空。
那麼使用 CFRelease 之後,要不要置為 NULL?
我在測試的時候發現,如果只是 CFRelease(cfPtr) 的話,釋放之後 cfPtr 裡面儲存的還是之前的地址,如果在執行 cfPtr = NULL 的話,cfPtr 的值才會變成 0x0000000000000000。也就是說 CFRelease 也需要置 NULL 才能清空指標。

那為什麼平時看別人寫的程式碼中似乎沒有這樣的操作?我覺得是當程式執行完函式後 cfPtr 在棧上的空間會被銷燬,一般不會造成問題。

以上是個人的看法,如果有誤的話請指出來!

相關文章