Re: [問題] 簡單的程式就有 memory leak 了

看板MacDev作者 (吹笛牧童)時間10年前 (2014/04/16 20:12), 10年前編輯推噓5(5055)
留言60則, 7人參與, 最新討論串4/4 (看更多)
來看看 MFC 怎麼實作 CString MFC 在 CString 也是用一種 ref count 機制 而且 MFC 完全公開 source code,也沒擴充保留字 有人還把它給拷了,送到沒 MFC 但有 C++ 的地方去用 網路上好像找得到,叫 CxString (至少敝公司有維護一套) CString F1() { CString str = "xxx"; // 產生一個字串, ref = 1 return str; // 使用 RC 的書怎麼教的? 書上說 str 在離開堆疊時就消失了, // 所以要 retain } 那 CString 怎麼做呢? 以下是我理解的看法 (書上不是這樣教的,總之 source code 公開,去 trace 一下可以印證我的看法) 它把函式的輸出結果也當一個變數 你可以想像有一個變數叫做 CString ret; 所以在 F1() 的最後一行, return str; 其實是執行了 ret = str; 然後外面 caller 端再去接這個 ret 比如 caller 端如果是寫 CString str2 = F1(); 那這裏就等於有 str2 = ret; //這個 ret 是剛剛 F1 函式的傳回值 然後 ret 就釋放了 (寫在 CString 的 destructor, ~CString) 如果沒人去接,也就是單純呼叫 F1() 那 ret 也會先接,然後再釋放 總之 ref count 的計算是完美的 然後在 ref count 為 0 時, CString 會把內部物件真的釋放掉 這一切,不必 precompiler 特別幫忙,不必擴充 C++ 它是由標準 C++ 組成的 MFC 完成的,可以轉移到沒有 MFC 的 C++ compiler 去 若說有什麼缺點.. 有 那就是只有 CString 寫這麼好用 如果我想自己寫一個 class, 就不會自動被賦與這麼漂亮的機制,要 coding 一堆東西 這其中包括要去覆寫 operator, constructor, destructor 等等 然後還有很煩的,比如 operator + 這個 function, 和 const operator + 是不一樣的 (就是多了個 const 而已啊..) 要各別覆寫,即使內部的 code 其實是一模一樣 operator = 和 constructor 可能是不一樣的 差異在 ref count 的計算方式 也就是說,想打造一個自己的 class 和 CString 一樣好用,要寫很多 code 比較簡單的方法是 template,不過我和它不熟 聽說用 template 可以很快的產生自己的 auto ref count style class..... 在看到 Obj C 的 ARC 時,我以為它是完美的把這套搬進 Compiler 所以我就這麼寫 - (NSString*)F1 { NSString* str = @"xxx"; return str; } 外面 caller 端是 NSString* str2 = [self F1]; 以上對 ref 的討論會一模一樣嗎? 也就是函式執行結束時,等於有一個中介變數 ret 如果有這種東西,那其實是用不到 autorelease 才對 因為 compiler 幫我們加了 retain & release return str; //這裏要往外傳,所以加一個 retain [self F1]; //這裏是 caller 端的角度,已經傳出來了,所以加一個 release NString* str2 = [self F1]; // 這種有 str2 來接,所以會先幫 str2 加一個 retain, 再幫函式的傳回值加一個 release, 兩個剛好對消, ref count 不變 如果一切像我想的這麼完美,那應該用不到 autorelease 我是這麼希望的啦 ---- 然後前面我說,我知道我的程式沒有 memory leak, 這是我長久以來的筆誤 其實是記憶體佔用但沒釋放,不知該叫什麼 嗯,我找到接近的 ~^_^~ http://blog.eddie.com.tw/2010/11/22/memory-management-in-objective-c/ > 又或許你會覺得這樣一顆小物件是能佔多少記憶體。這種東西積沙成塔的, > 你借了記憶體來用卻沒還回去,久了可能就會造成”漏水”(memory leaking)的情況 看,它沒犯我的錯誤,它不是說"這叫 memory leaking" 它是說,這可能會"造成" memory leaking (照我上一篇的問題,這哪有 leak? 你一直有 pointer 指著它,它就不是 leak) 我現在還是為這樣的溝通困擾著 而且如果 arc 這機制是 ref count 為 0 時就呼叫 dealloc 那我也搞不懂為什麼會有 leak -- 活動/美食計劃 蘭嶼 魚白 勝興車站 星月天空 武陵 草嶺古道 嘉義阿里山小火車 保齡球  司馬庫斯 手包水餃 日月潭纜車 合歡攻頂 馬祖 鹽山 南庄 澎湖 溪頭/松林町 南投天梯 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 60.251.197.63 ※ 文章網址: http://www.ptt.cc/bbs/MacDev/M.1397650361.A.2BE.html

04/16 21:15, , 1F
安安, 請問知道什麼叫 stack allocation 嗎?
04/16 21:15, 1F
不是很清楚 我知道一些,但有人叫我不要硬套 所以是否請你完整說明,我來對照一下

04/16 22:19, , 2F
CString 不做 Reference Counting
04/16 22:19, 2F
可以去看一下它裏面怎麼做的 如果有二十個字串,當初都從同一個地方拷貝出來 那要二十倍的記憶體嗎? MFC 有想到要節省這個記憶體,它安排了它的方式 如果你說那不是 ref counting,我也不能說你錯 因為它'沒有完全一樣' 但它有它的一套,也很完整

04/17 01:05, , 3F
1.早就叫你不要老是不管ObjC怎麼做,老是拿其他東西來
04/17 01:05, 3F

04/17 01:07, , 4F
"以為"硬套 2.@"ooxx"這種NSString是特例,拿這來看看不
04/17 01:07, 4F

04/17 01:08, , 5F
懂的
04/17 01:08, 5F
謝謝指教

04/17 01:36, , 6F
rc是一種ownership policy, 編譯器只管你有沒有符合rc規範,
04/17 01:36, 6F

04/17 01:37, , 7F
不會去猜測你的程式為什麼會留著物件不用.
04/17 01:37, 7F
也不能說猜測啦,以我舉的 CString 來說 它是很明確而且很有效很完整的處理了指標的 ref counting 它沒特別擴充 C++ 啊 而我們知道 Obj C++ 是 C++ 的超集 也就是說,至少如果我把這套搬進 compiler, 是絕對可行的邏輯;夠完整 我問的就是: Obj C 用的方法,有哪裏不一樣嗎? 不過我現在知道,我可以用個指令去讀出目前的 ref counting 為多少 這多少對驗證 compiler 的行為有幫助;不然我都不知它哪裏做的和我預期不同了

04/17 01:40, , 8F
另外,要用Instrument就弄清楚工具真正的用法及意義,不要自
04/17 01:40, 8F

04/17 01:41, , 9F
己單看圖表就猜測。以你附的圖來說,記憶體升高又降低,就代
04/17 01:41, 9F

04/17 01:42, , 10F
表有用到也有釋放, Allocation保持一定的記憶體是原本程式
04/17 01:42, 10F

04/17 01:43, , 11F
跑起來就需要的,與Leak完全無關。
04/17 01:43, 11F
應該不是說 leak,而是說'佔用而沒釋放';我前面說過了,這是我長年來的筆誤 我發現我同事和我一樣會誤用這個名詞,所以我們溝通還沒問題 現在的狀況是,程式不是一個人寫的,是大家寫的 所以我們見到一塊記憶體沒釋放(並不是 leak),就會互推責任 這狀況很糟啊,所以不是很計較記憶體捨不得用 而是,即使連一個 byte 都希望不要多出來 這樣才劃得清責任 我的模組完成了,才能交給別人 (假設我的模組是較核心,被呼叫的副程式) 用得記憶體雖然少,但來回幾次就愈用愈多 就算只有2K,3K,也難保不會被人說'抓到了,人是你殺的' 如果說因為某些指令,內部是用 auto release 寫的 所以必需到 @autorelease 時才能釋放 那最好我就加這個東西,釋放完才把副程式交給同事 這樣完全厘清,對團隊合作會比較好

04/17 01:44, , 12F
rc這東西在c++也有,去看看STL smart_ptr是怎麼回事,去讀一下
04/17 01:44, 12F

04/17 01:45, , 13F
Modern C++ Design(C++設計新思維), Boost, Google的資料也
04/17 01:45, 13F

04/17 01:46, , 14F
很多...
04/17 01:46, 14F
在 COM 裏面我也見過一次 不過這些都別提了 不是老有人叫我不要拿以前學過的東西來跘住自己嘛

04/17 02:41, , 15F
基本上,如果你自己都已經能找到高見龍的文章來看,那應
04/17 02:41, 15F

04/17 02:41, , 16F
該就是個會用Google的人,看你能舉那麼多MFC的東西,應
04/17 02:41, 16F

04/17 02:42, , 17F
該不會是個程式新手。那為什麼會搞成現在這種局面呢?就
04/17 02:42, 17F

04/17 02:43, , 18F
是"倚老賣老"這四個字造成的,老是以為能拿以前對事物的
04/17 02:43, 18F

04/17 02:44, , 19F
理解來硬套,然後自己覺得怪怪的,就開始用些更旁門左道
04/17 02:44, 19F

04/17 02:45, , 20F
的方法來硬幹。總歸一句,就是根基不穩,然後照你這種個
04/17 02:45, 20F

04/17 02:45, , 21F
性,我覺得網路上這種一篇一篇的文章給你看了大概也不會
04/17 02:45, 21F

04/17 02:46, , 22F
有幫助。要我給建議的話,你還是放下無謂的堅持,買本書
04/17 02:46, 22F

04/17 02:46, , 23F
來看吧。
04/17 02:46, 23F
謝謝指教

04/17 04:23, , 24F
Apple一直在持續改善ObjC, 從語言本身到compiler, 所以
04/17 04:23, 24F

04/17 04:24, , 25F
有些資訊比較混亂, 真的要深入看, 還是得仔細看官方的技
04/17 04:24, 25F

04/17 04:25, , 26F
術文件, 再配上其他人的解說, stackoverflow是最好的地
04/17 04:25, 26F

04/17 04:26, , 27F
方, 不過keyword可能要花點心思.
04/17 04:26, 27F

04/17 04:27, , 28F
的確... 其實我有時是從兩三個互相對立的答案中挑一個
04/17 04:27, 28F

04/17 04:28, , 29F
就好像這次,有人說'會馬上釋放',也有人說'不會'
04/17 04:28, 29F

04/17 04:28, , 30F
我覺得大家貢獻自己想法來討論很好啊
04/17 04:28, 30F

04/17 04:28, , 31F
奇怪的是我提 MFC 來對照,突然被說'別提以前的經驗了'
04/17 04:28, 31F

04/17 04:29, , 32F
那 ref counting 我讀的書,就只有簡短幾句話
04/17 04:29, 32F

04/17 04:29, , 33F
"它是 precompiler 自動幫你插入 retain/release"
04/17 04:29, 33F
這樣說吧,其實 C 的 precompiler 是有獨立程式可以看結果的 *.c 可以 compile 成 *.i 這 *.i 很繁鎖,但也有助於厘清問題,看 precompiler 做的和你想的有沒有一樣 如果說 ARC 就是 precompiler 幫忙插入 retain/release 那有沒有這樣一支程式把 *.m 轉成 *.i 如果有,我也不用再猜,就可以靜靜的實驗一些東西 不然老說看書,書上寫得少啊 手上兩本書都在教沒有 ARC 的版本

04/17 04:31, , 34F
所以我拿 MFC 下學到它何時加一,何時減一,不也是個討論的
04/17 04:31, 34F

04/17 04:31, , 35F
起點..
04/17 04:31, 35F

04/17 04:32, , 36F
我一個同事說:看書太慢,google 比較快
04/17 04:32, 36F

04/17 04:33, , 37F
主管說:別上網問了,我不信會寫的人會在網路上玩
04/17 04:33, 37F

04/17 08:16, , 38F
1. 沒人說你不能用以前的經驗來理解現在的東西,但是注
04/17 08:16, 38F

04/17 08:17, , 39F
意,是"理解",不是"硬套"。其他地方的經驗只是"輔助",
04/17 08:17, 39F

04/17 08:18, , 40F
而不是像你現在這樣"MFC是怎樣,ObjC就應該是怎樣"
04/17 08:18, 40F
要一句句講贏你不難,但吵贏後我反而會變輸家 我只回應這句 > "MFC是怎樣,ObjC就應該是怎樣" 我是這樣表達的嗎? 如果你看成這意思,那我道歉 我的意思是"我理解 MFC 是這樣的,請問 Obj C 是怎麼做的" 所以我對你只有一個請求:我知道自己的作業自己做 如果你認為套別種語言的經驗不好的話,請你不要再回應 因為有其他人是可以接受這種經驗的 學生時有一次在餐廳,同學間討論問題,我就坐在旁邊 就該領域,很明顯我領先他們,但因為太常問我了,所以連飯都沒空吃 同學也很體諒,就沒再問我了 旁聽時我感覺講解的同學錯了,但我並沒去糾正 因為如果要糾正,一定是落落長一大篇 但那多少是滿足一種潔癖而已 用另一種講法來翻譯同學間的對話,大概像這樣 甲:地球是什麼型狀的? 乙:地球是圓型的 我心中OS:才怪,地球是橢圓型的 看出問題沒有?我有必要糾正到這境界嗎? 而就算我說地球是橢圓型的,就沒錯誤了嗎? 如果我這樣插嘴: 才不是圓型的,至於什麼型狀我就不說了,你不會去看置底啊 請問有什麼幫助? 要放話就要完整 不然就讓其他人去發揮 教地球是圓型的同學也是熱心,也節省了我的時間 我不懂這樣是有什麼不對了

04/17 08:19, , 41F
2.Google是針對"遇到特定問題"的時候會比較快,但是現在
04/17 08:19, 41F

04/17 08:19, , 42F
看來,你,或者你們整個team,都不是能夠觸類旁通,也都
04/17 08:19, 42F

04/17 08:19, , 43F
沒有基礎,這樣用Google硬幹,只是連關鍵字都不知道怎麼
04/17 08:19, 43F

04/17 08:20, , 44F
下而已。整串下來,也不止我一個跟你講了,不打基礎,那
04/17 08:20, 44F

04/17 08:20, , 45F
就去找個懂的人加入你們team。你主管豬頭覺得東西都一樣
04/17 08:20, 45F

04/17 08:23, , 46F
要你們只學過英文卻連あいうえお都搞不清楚的去翻譯阪上
04/17 08:23, 46F

04/17 08:24, , 47F
之雲,不代表你就只能把每段話丟到Google翻譯剪下貼上交
04/17 08:24, 47F

04/17 08:24, , 48F
差了事 (當然如果你本來就是這種個性...那就算了)
04/17 08:24, 48F

04/17 08:25, , 49F
3.會寫的人不會在網路上玩?自己google一下zonble、高見
04/17 08:25, 49F

04/17 08:26, , 50F
龍、xdite,看他們夠不夠格稱得上"會寫",再看看他們有
04/17 08:26, 50F

04/17 08:26, , 51F
沒有在網路上"玩"
04/17 08:26, 51F

04/17 08:26, , 52F
4.找書?沒看置底文?
04/17 08:26, 52F

04/17 08:28, , 53F
5.最後回應一下為什麼書都在教沒有ARC的版本,因為ARC就
04/17 08:28, 53F

04/17 08:28, , 54F
只是自動加入retain/release,所以如果你真的要管好記憶
04/17 08:28, 54F
因為 MFC 只是自動加入 add ref count / remove ref count 所以也有助於理解 ARC 看,一樣說得通 要說不通就指出來: ARC 的 ref count 和 MFC 的做法不同 要不然,有用 ref count 的語言,其實也不只 C++/MFC 多得是觸類旁通的機會,做法也大同小異 我相信大部份人都因為過往的經驗而縮短了學習的時間

04/17 08:28, , 55F
體,了解沒有ARC的時候是怎麼運作的還是有相當大的幫助
04/17 08:28, 55F

04/17 08:29, , 56F
或者這樣講吧,把手動管理學起來,轉用ARC只是一篇簡單
04/17 08:29, 56F

04/17 08:29, , 57F
教學的事
04/17 08:29, 57F
我知道,所以我不可以發一篇 MFC 的作法來比較嗎? 我發了後,就是指責 Obj C '怎麼不用這種做法'嗎? 雖然我可以承認自己溝通有問題 但長此以往,再裝就不像了 除了謝謝指教,我還能說什麼?

04/17 11:22, , 58F
instruments裡面可以看各物件占用的記憶體
04/17 11:22, 58F

04/17 11:24, , 59F
記憶體吃太多,應該找出吃記憶體的物件
04/17 11:24, 59F

04/17 11:25, , 60F
加一減一那是知識,不是拿來實務用的,不知道也可以寫
04/17 11:25, 60F
剛和同事討論,同事還是用 memory leak 這個字眼 我稍微解釋一下後,他回我: 反正還不是一樣,都不正常 好啦,反正來回於兩個用字不同的群組間,就是要有一個人擔任翻譯 所以同事說 memory leak 時,我就自動翻譯成'記憶體佔用' ※ 編輯: HuangJC (60.251.197.63), 04/17/2014 15:12:15
文章代碼(AID): #1JJdEvA- (MacDev)
文章代碼(AID): #1JJdEvA- (MacDev)