Re: [問題] 簡單的程式就有 memory leak 了
來看看 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
04/16 21:15, 1F
不是很清楚
我知道一些,但有人叫我不要硬套
所以是否請你完整說明,我來對照一下
推
04/16 22:19, , 2F
04/16 22:19, 2F
可以去看一下它裏面怎麼做的
如果有二十個字串,當初都從同一個地方拷貝出來
那要二十倍的記憶體嗎?
MFC 有想到要節省這個記憶體,它安排了它的方式
如果你說那不是 ref counting,我也不能說你錯
因為它'沒有完全一樣'
但它有它的一套,也很完整
推
04/17 01:05, , 3F
04/17 01:05, 3F
→
04/17 01:07, , 4F
04/17 01:07, 4F
→
04/17 01:08, , 5F
04/17 01:08, 5F
謝謝指教
→
04/17 01:36, , 6F
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
04/17 01:40, 8F
→
04/17 01:41, , 9F
04/17 01:41, 9F
→
04/17 01:42, , 10F
04/17 01:42, 10F
→
04/17 01:43, , 11F
04/17 01:43, 11F
應該不是說 leak,而是說'佔用而沒釋放';我前面說過了,這是我長年來的筆誤
我發現我同事和我一樣會誤用這個名詞,所以我們溝通還沒問題
現在的狀況是,程式不是一個人寫的,是大家寫的
所以我們見到一塊記憶體沒釋放(並不是 leak),就會互推責任
這狀況很糟啊,所以不是很計較記憶體捨不得用
而是,即使連一個 byte 都希望不要多出來
這樣才劃得清責任
我的模組完成了,才能交給別人 (假設我的模組是較核心,被呼叫的副程式)
用得記憶體雖然少,但來回幾次就愈用愈多
就算只有2K,3K,也難保不會被人說'抓到了,人是你殺的'
如果說因為某些指令,內部是用 auto release 寫的
所以必需到 @autorelease 時才能釋放
那最好我就加這個東西,釋放完才把副程式交給同事
這樣完全厘清,對團隊合作會比較好
→
04/17 01:44, , 12F
04/17 01:44, 12F
→
04/17 01:45, , 13F
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
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
04/17 04:23, 24F
→
04/17 04:24, , 25F
04/17 04:24, 25F
→
04/17 04:25, , 26F
04/17 04:25, 26F
→
04/17 04:26, , 27F
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
04/17 04:28, 31F
→
04/17 04:29, , 32F
04/17 04:29, 32F
→
04/17 04:29, , 33F
04/17 04:29, 33F
這樣說吧,其實 C 的 precompiler 是有獨立程式可以看結果的
*.c 可以 compile 成 *.i
這 *.i 很繁鎖,但也有助於厘清問題,看 precompiler 做的和你想的有沒有一樣
如果說 ARC 就是 precompiler 幫忙插入 retain/release
那有沒有這樣一支程式把 *.m 轉成 *.i
如果有,我也不用再猜,就可以靜靜的實驗一些東西
不然老說看書,書上寫得少啊
手上兩本書都在教沒有 ARC 的版本
→
04/17 04:31, , 34F
04/17 04:31, 34F
→
04/17 04:31, , 35F
04/17 04:31, 35F
→
04/17 04:32, , 36F
04/17 04:32, 36F
→
04/17 04:33, , 37F
04/17 04:33, 37F
推
04/17 08:16, , 38F
04/17 08:16, 38F
→
04/17 08:17, , 39F
04/17 08:17, 39F
→
04/17 08:18, , 40F
04/17 08:18, 40F
要一句句講贏你不難,但吵贏後我反而會變輸家
我只回應這句
> "MFC是怎樣,ObjC就應該是怎樣"
我是這樣表達的嗎? 如果你看成這意思,那我道歉
我的意思是"我理解 MFC 是這樣的,請問 Obj C 是怎麼做的"
所以我對你只有一個請求:我知道自己的作業自己做
如果你認為套別種語言的經驗不好的話,請你不要再回應
因為有其他人是可以接受這種經驗的
學生時有一次在餐廳,同學間討論問題,我就坐在旁邊
就該領域,很明顯我領先他們,但因為太常問我了,所以連飯都沒空吃
同學也很體諒,就沒再問我了
旁聽時我感覺講解的同學錯了,但我並沒去糾正
因為如果要糾正,一定是落落長一大篇
但那多少是滿足一種潔癖而已
用另一種講法來翻譯同學間的對話,大概像這樣
甲:地球是什麼型狀的?
乙:地球是圓型的
我心中OS:才怪,地球是橢圓型的
看出問題沒有?我有必要糾正到這境界嗎?
而就算我說地球是橢圓型的,就沒錯誤了嗎?
如果我這樣插嘴:
才不是圓型的,至於什麼型狀我就不說了,你不會去看置底啊
請問有什麼幫助? 要放話就要完整
不然就讓其他人去發揮
教地球是圓型的同學也是熱心,也節省了我的時間
我不懂這樣是有什麼不對了
→
04/17 08:19, , 41F
04/17 08:19, 41F
→
04/17 08:19, , 42F
04/17 08:19, 42F
→
04/17 08:19, , 43F
04/17 08:19, 43F
→
04/17 08:20, , 44F
04/17 08:20, 44F
→
04/17 08:20, , 45F
04/17 08:20, 45F
→
04/17 08:23, , 46F
04/17 08:23, 46F
→
04/17 08:24, , 47F
04/17 08:24, 47F
→
04/17 08:24, , 48F
04/17 08:24, 48F
→
04/17 08:25, , 49F
04/17 08:25, 49F
→
04/17 08:26, , 50F
04/17 08:26, 50F
→
04/17 08:26, , 51F
04/17 08:26, 51F
→
04/17 08:26, , 52F
04/17 08:26, 52F
→
04/17 08:28, , 53F
04/17 08:28, 53F
→
04/17 08:28, , 54F
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
04/17 08:28, 55F
→
04/17 08:29, , 56F
04/17 08:29, 56F
→
04/17 08:29, , 57F
04/17 08:29, 57F
我知道,所以我不可以發一篇 MFC 的作法來比較嗎?
我發了後,就是指責 Obj C '怎麼不用這種做法'嗎?
雖然我可以承認自己溝通有問題
但長此以往,再裝就不像了
除了謝謝指教,我還能說什麼?
→
04/17 11:22, , 58F
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
討論串 (同標題文章)
完整討論串 (本文為第 4 之 4 篇):
MacDev 近期熱門文章
PTT數位生活區 即時熱門文章