看板 C_and_CPP 關於我們 聯絡資訊
許多教程式的教授或是工程師會認為一個好的程式中 free() 與 *alloc() 必須成對。 通常執行 free() 並不會把 memory 還給 operating system, 反而是告訴程式,下一次 *alloc() 的時候,可以用一下之前 free() 過的空間。 這種設計並不壞,主要是為了節省 system call 的時間消耗。 雖然心中覺得成對會比較嚴謹一點,不過在實作的時候確實會容易造成問題。 問題一: 前一個人 free() 掉之後,並沒有把指標設成 NULL,然後還在 code 中到處流串, 只要一不小心,*** glibc detected *** double free or corruption 就會死給你看, 這種 bug 最噁心了,尤其在其他 code 不是你寫的時候。 問題二: 當一個函數的回傳值是一個指向空間的指標的時候, 而且這個函數會將這個指標送給超過一個的函數的話, 只要其中一個函數 free() 掉之後,其他的函數也會跟著遭殃, 通常會送個 Segmentation fault (core dumped) 當作聖誕節禮物。 程式在結束的時候,大部分的作業系統都會回收記憶體, 所以,若在程式碼結尾的地方 free() 掉所有申請過的空間,也是多此一舉。 我的看法是,若該指標出現在迴圈中或是遞迴中的話,才有使用 free() 的必要, 其餘的指標就讓作業系統去回收吧,畢竟通常吃記憶體的怪獸都是迴圈或遞迴中的指標。 大家怎麼看?通常都會嚴格遵守成對的習慣嗎? -- 當教授在講臺上C++的時候,我的臉比佳佳還要沮喪... 講正經的... C++是一個被過度設計的程式語言,完全遭透了! -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.241.158.22 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1434264021.A.274.html ※ 編輯: Hazukashiine (111.241.158.22), 06/14/2015 14:40:33
LiloHuang: 還好我寫 C++ 我用 smart pointer (boost::shared_ptr) 06/14 14:46
LiloHuang: 倒是看過不少人會定義一個 SAFE_FREE macro 來設 NULL 06/14 14:46
LiloHuang: 至於 free 會不會真的還給作業系統要看 C-Runtime 實作 06/14 14:47
LiloHuang: glibc 可以用 malloc_stats() 來看有沒有還回去 06/14 14:48
哦~ 看起來 malloc_stats() 不錯用哦~XDD ※ 編輯: Hazukashiine (111.241.158.22), 06/14/2015 14:50:54
LiloHuang: 至於 MSVCRT 的話,我沒記錯 free 每次都還回去就是 :) 06/14 14:50
chchwy: 你當記憶體用不完阿 不還很快就沒了 06/14 14:57
azureblaze: 不free你也只是把問題晾在那邊沒解決啊 06/14 15:09
kevingwn: 問題1&2的癥結都在於:不要free()不是你*alloc()出來的指 06/14 15:09
kevingwn: 標,例如某DLL是用gcc編譯,你在MSVC的程式去free()它的指 06/14 15:09
kevingwn: 標會有不可預期的結果 06/14 15:09
不要 free() 不是我 *alloc 出的指標, 但是如果像是這樣怎麼辦?@@? A.cpp written by Mr.A char *ret_string(const char* str_1) { char *str_2 = malloc(sizeof(char) * (strlen(str) + 1)) strcpy(str_2, str_1); return str_2; } B.cpp written by myself int main(void) { printf("%s", ret_string("hello!")); } 如果不去 free() 不是我 *alloc 出的指標,這樣一來,不就 memory leak 了?
kevingwn: 問題3:遵守成對是寫C的基本,對此有疑慮建議改用有垃圾回 06/14 15:10
kevingwn: 收機制的語言 06/14 15:10
如果是像上述的情況,要怎麼遵守成對? 這兩個程式的片段很可能會在不同的檔案的小角落中...
uranusjr: 兩個問題都是因為沒有正確讓它們成對, 成對本身沒有問題 06/14 15:12
bibo9901: 推樓上 06/14 15:40
Qbsuran: 照這樣想法如果去寫infinity loop 很快就會掛掉 不是所 06/14 15:59
Qbsuran: 有程式都要結束 06/14 16:00
suhorng: 可是迴圈很多耶, 像是跑不停的伺服器程式 06/14 16:23
suhorng: 不能一直不 free 下去呀 06/14 16:24
suhorng: 一次性跑一下就沒了的程式就算了 06/14 16:24
azureblaze: 要求使用著自己弄一塊記憶體給你寫 06/14 16:33
azureblaze: 或是用alloc_str() free_str()給使用者 06/14 16:33
azureblaze: 就像fopen和fclose也得成對 06/14 16:35
azureblaze: 這是一定得處理的問題,等程式結束絕對不是解決方案 06/14 16:38
恩~理解了~感謝樓上大大 >__<
kevingwn: 這種情況free()的責任在Mr.A而不在B,通常A要提供另一個 06/14 17:38
kevingwn: 函式給B,B應該呼叫該函式讓A有機會free(),而不是直接使 06/14 17:38
kevingwn: 用free() 因為A&B可能經不同的編譯後才連結兩者的malloc 06/14 17:40
kevingwn: 及free來自不同的c runtime,混用將造成不可預期的結果 06/14 17:41
kevingwn: 若一起編譯的話當然沒問題,但結果是A&B這對CP不可拆不可 06/14 17:41
kevingwn: 逆XD不是良好的設計 06/14 17:41
ah7675: 你是不是沒修過作業系統@@? 06/14 23:35
還沒哦~ 0.0 ※ 編輯: Hazukashiine (140.113.91.124), 06/15/2015 03:10:42
Killercat: 現代OS多半都能回收,但是這並沒有保證 06/15 18:26
Killercat: 我個人會建議記得的話還是寫一下 06/15 18:26
cobrasgo: c不只用在pc上,在mcu上這樣搞就死定了 06/16 18:30
Killercat: 應該說 在非保護模式的OS上 一定死 XD 06/17 17:56