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

作者: HuangJC (吹笛牧童)   2014-04-16 20:12:36
來看看 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
我是這麼希望的啦
作者: uranusjr (←這人是超級笨蛋)   2014-04-16 21:15:00
安安, 請問知道什麼叫 stack allocation 嗎?
作者: timTan (用口頭禪區分年記)   2014-04-16 22:19:00
CString 不做 Reference Counting
作者: Blueshiva (龍野南雲)   2014-04-17 01:05:00
1.早就叫你不要老是不管ObjC怎麼做,老是拿其他東西來"以為"硬套 2.@"ooxx"這種NSString是特例,拿這來看看不懂的
作者: atst2 (atst2)   2014-04-17 01:36:00
rc是一種ownership policy, 編譯器只管你有沒有符合rc規範,不會去猜測你的程式為什麼會留著物件不用.另外,要用Instrument就弄清楚工具真正的用法及意義,不要自己單看圖表就猜測。以你附的圖來說,記憶體升高又降低,就代表有用到也有釋放, Allocation保持一定的記憶體是原本程式跑起來就需要的,與Leak完全無關。rc這東西在c++也有,去看看STL smart_ptr是怎麼回事,去讀一下Modern C++ Design(C++設計新思維), Boost, Google的資料也很多...
作者: Blueshiva (龍野南雲)   2014-04-17 02:41:00
基本上,如果你自己都已經能找到高見龍的文章來看,那應該就是個會用Google的人,看你能舉那麼多MFC的東西,應該不會是個程式新手。那為什麼會搞成現在這種局面呢?就是"倚老賣老"這四個字造成的,老是以為能拿以前對事物的理解來硬套,然後自己覺得怪怪的,就開始用些更旁門左道的方法來硬幹。總歸一句,就是根基不穩,然後照你這種個性,我覺得網路上這種一篇一篇的文章給你看了大概也不會有幫助。要我給建議的話,你還是放下無謂的堅持,買本書來看吧。
作者: abcdefghi   2014-04-17 04:23:00
Apple一直在持續改善ObjC, 從語言本身到compiler, 所以有些資訊比較混亂, 真的要深入看, 還是得仔細看官方的技術文件, 再配上其他人的解說, stackoverflow是最好的地方, 不過keyword可能要花點心思.
作者: HuangJC (吹笛牧童)   2014-04-17 04:27:00
的確... 其實我有時是從兩三個互相對立的答案中挑一個就好像這次,有人說'會馬上釋放',也有人說'不會'我覺得大家貢獻自己想法來討論很好啊奇怪的是我提 MFC 來對照,突然被說'別提以前的經驗了'那 ref counting 我讀的書,就只有簡短幾句話"它是 precompiler 自動幫你插入 retain/release"所以我拿 MFC 下學到它何時加一,何時減一,不也是個討論的起點..我一個同事說:看書太慢,google 比較快主管說:別上網問了,我不信會寫的人會在網路上玩
作者: Blueshiva (龍野南雲)   2014-04-17 08:16:00
1. 沒人說你不能用以前的經驗來理解現在的東西,但是注意,是"理解",不是"硬套"。其他地方的經驗只是"輔助",而不是像你現在這樣"MFC是怎樣,ObjC就應該是怎樣"2.Google是針對"遇到特定問題"的時候會比較快,但是現在看來,你,或者你們整個team,都不是能夠觸類旁通,也都沒有基礎,這樣用Google硬幹,只是連關鍵字都不知道怎麼下而已。整串下來,也不止我一個跟你講了,不打基礎,那就去找個懂的人加入你們team。你主管豬頭覺得東西都一樣要你們只學過英文卻連あいうえお都搞不清楚的去翻譯阪上之雲,不代表你就只能把每段話丟到Google翻譯剪下貼上交差了事 (當然如果你本來就是這種個性...那就算了)3.會寫的人不會在網路上玩?自己google一下zonble、高見龍、xdite,看他們夠不夠格稱得上"會寫",再看看他們有沒有在網路上"玩"4.找書?沒看置底文?5.最後回應一下為什麼書都在教沒有ARC的版本,因為ARC就只是自動加入retain/release,所以如果你真的要管好記憶體,了解沒有ARC的時候是怎麼運作的還是有相當大的幫助或者這樣講吧,把手動管理學起來,轉用ARC只是一篇簡單教學的事
作者: howdiun (Howdiun)   2014-04-17 11:22:00
instruments裡面可以看各物件占用的記憶體記憶體吃太多,應該找出吃記憶體的物件加一減一那是知識,不是拿來實務用的,不知道也可以寫

Links booklink

Contact Us: admin [ a t ] ucptt.com