看板 MacDev 關於我們 聯絡資訊
來看看 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
uranusjr:安安, 請問知道什麼叫 stack allocation 嗎? 04/16 21:15
不是很清楚 我知道一些,但有人叫我不要硬套 所以是否請你完整說明,我來對照一下
timTan:CString 不做 Reference Counting 04/16 22:19
可以去看一下它裏面怎麼做的 如果有二十個字串,當初都從同一個地方拷貝出來 那要二十倍的記憶體嗎? MFC 有想到要節省這個記憶體,它安排了它的方式 如果你說那不是 ref counting,我也不能說你錯 因為它'沒有完全一樣' 但它有它的一套,也很完整
Blueshiva:1.早就叫你不要老是不管ObjC怎麼做,老是拿其他東西來 04/17 01:05
Blueshiva:"以為"硬套 2.@"ooxx"這種NSString是特例,拿這來看看不 04/17 01:07
Blueshiva:懂的 04/17 01:08
謝謝指教
atst2:rc是一種ownership policy, 編譯器只管你有沒有符合rc規範, 04/17 01:36
atst2:不會去猜測你的程式為什麼會留著物件不用. 04/17 01:37
也不能說猜測啦,以我舉的 CString 來說 它是很明確而且很有效很完整的處理了指標的 ref counting 它沒特別擴充 C++ 啊 而我們知道 Obj C++ 是 C++ 的超集 也就是說,至少如果我把這套搬進 compiler, 是絕對可行的邏輯;夠完整 我問的就是: Obj C 用的方法,有哪裏不一樣嗎? 不過我現在知道,我可以用個指令去讀出目前的 ref counting 為多少 這多少對驗證 compiler 的行為有幫助;不然我都不知它哪裏做的和我預期不同了
atst2:另外,要用Instrument就弄清楚工具真正的用法及意義,不要自 04/17 01:40
atst2:己單看圖表就猜測。以你附的圖來說,記憶體升高又降低,就代 04/17 01:41
atst2:表有用到也有釋放, Allocation保持一定的記憶體是原本程式 04/17 01:42
atst2:跑起來就需要的,與Leak完全無關。 04/17 01:43
應該不是說 leak,而是說'佔用而沒釋放';我前面說過了,這是我長年來的筆誤 我發現我同事和我一樣會誤用這個名詞,所以我們溝通還沒問題 現在的狀況是,程式不是一個人寫的,是大家寫的 所以我們見到一塊記憶體沒釋放(並不是 leak),就會互推責任 這狀況很糟啊,所以不是很計較記憶體捨不得用 而是,即使連一個 byte 都希望不要多出來 這樣才劃得清責任 我的模組完成了,才能交給別人 (假設我的模組是較核心,被呼叫的副程式) 用得記憶體雖然少,但來回幾次就愈用愈多 就算只有2K,3K,也難保不會被人說'抓到了,人是你殺的' 如果說因為某些指令,內部是用 auto release 寫的 所以必需到 @autorelease 時才能釋放 那最好我就加這個東西,釋放完才把副程式交給同事 這樣完全厘清,對團隊合作會比較好
atst2:rc這東西在c++也有,去看看STL smart_ptr是怎麼回事,去讀一下 04/17 01:44
atst2:Modern C++ Design(C++設計新思維), Boost, Google的資料也 04/17 01:45
atst2:很多... 04/17 01:46
在 COM 裏面我也見過一次 不過這些都別提了 不是老有人叫我不要拿以前學過的東西來跘住自己嘛
Blueshiva:基本上,如果你自己都已經能找到高見龍的文章來看,那應 04/17 02:41
Blueshiva:該就是個會用Google的人,看你能舉那麼多MFC的東西,應 04/17 02:41
Blueshiva:該不會是個程式新手。那為什麼會搞成現在這種局面呢?就 04/17 02:42
Blueshiva:是"倚老賣老"這四個字造成的,老是以為能拿以前對事物的 04/17 02:43
Blueshiva:理解來硬套,然後自己覺得怪怪的,就開始用些更旁門左道 04/17 02:44
Blueshiva:的方法來硬幹。總歸一句,就是根基不穩,然後照你這種個 04/17 02:45
Blueshiva:性,我覺得網路上這種一篇一篇的文章給你看了大概也不會 04/17 02:45
Blueshiva:有幫助。要我給建議的話,你還是放下無謂的堅持,買本書 04/17 02:46
Blueshiva:來看吧。 04/17 02:46
謝謝指教
abcdefghi:Apple一直在持續改善ObjC, 從語言本身到compiler, 所以 04/17 04:23
abcdefghi:有些資訊比較混亂, 真的要深入看, 還是得仔細看官方的技 04/17 04:24
abcdefghi:術文件, 再配上其他人的解說, stackoverflow是最好的地 04/17 04:25
abcdefghi:方, 不過keyword可能要花點心思. 04/17 04:26
HuangJC:的確... 其實我有時是從兩三個互相對立的答案中挑一個 04/17 04:27
HuangJC:就好像這次,有人說'會馬上釋放',也有人說'不會' 04/17 04:28
HuangJC:我覺得大家貢獻自己想法來討論很好啊 04/17 04:28
HuangJC:奇怪的是我提 MFC 來對照,突然被說'別提以前的經驗了' 04/17 04:28
HuangJC:那 ref counting 我讀的書,就只有簡短幾句話 04/17 04:29
HuangJC:"它是 precompiler 自動幫你插入 retain/release" 04/17 04:29
這樣說吧,其實 C 的 precompiler 是有獨立程式可以看結果的 *.c 可以 compile 成 *.i 這 *.i 很繁鎖,但也有助於厘清問題,看 precompiler 做的和你想的有沒有一樣 如果說 ARC 就是 precompiler 幫忙插入 retain/release 那有沒有這樣一支程式把 *.m 轉成 *.i 如果有,我也不用再猜,就可以靜靜的實驗一些東西 不然老說看書,書上寫得少啊 手上兩本書都在教沒有 ARC 的版本
HuangJC:所以我拿 MFC 下學到它何時加一,何時減一,不也是個討論的 04/17 04:31
HuangJC:起點.. 04/17 04:31
HuangJC:我一個同事說:看書太慢,google 比較快 04/17 04:32
HuangJC:主管說:別上網問了,我不信會寫的人會在網路上玩 04/17 04:33
Blueshiva:1. 沒人說你不能用以前的經驗來理解現在的東西,但是注 04/17 08:16
Blueshiva:意,是"理解",不是"硬套"。其他地方的經驗只是"輔助", 04/17 08:17
Blueshiva:而不是像你現在這樣"MFC是怎樣,ObjC就應該是怎樣" 04/17 08:18
要一句句講贏你不難,但吵贏後我反而會變輸家 我只回應這句 > "MFC是怎樣,ObjC就應該是怎樣" 我是這樣表達的嗎? 如果你看成這意思,那我道歉 我的意思是"我理解 MFC 是這樣的,請問 Obj C 是怎麼做的" 所以我對你只有一個請求:我知道自己的作業自己做 如果你認為套別種語言的經驗不好的話,請你不要再回應 因為有其他人是可以接受這種經驗的 學生時有一次在餐廳,同學間討論問題,我就坐在旁邊 就該領域,很明顯我領先他們,但因為太常問我了,所以連飯都沒空吃 同學也很體諒,就沒再問我了 旁聽時我感覺講解的同學錯了,但我並沒去糾正 因為如果要糾正,一定是落落長一大篇 但那多少是滿足一種潔癖而已 用另一種講法來翻譯同學間的對話,大概像這樣 甲:地球是什麼型狀的? 乙:地球是圓型的 我心中OS:才怪,地球是橢圓型的 看出問題沒有?我有必要糾正到這境界嗎? 而就算我說地球是橢圓型的,就沒錯誤了嗎? 如果我這樣插嘴: 才不是圓型的,至於什麼型狀我就不說了,你不會去看置底啊 請問有什麼幫助? 要放話就要完整 不然就讓其他人去發揮 教地球是圓型的同學也是熱心,也節省了我的時間 我不懂這樣是有什麼不對了
Blueshiva:2.Google是針對"遇到特定問題"的時候會比較快,但是現在 04/17 08:19
Blueshiva:看來,你,或者你們整個team,都不是能夠觸類旁通,也都 04/17 08:19
Blueshiva:沒有基礎,這樣用Google硬幹,只是連關鍵字都不知道怎麼 04/17 08:19
Blueshiva:下而已。整串下來,也不止我一個跟你講了,不打基礎,那 04/17 08:20
Blueshiva:就去找個懂的人加入你們team。你主管豬頭覺得東西都一樣 04/17 08:20
Blueshiva:要你們只學過英文卻連あいうえお都搞不清楚的去翻譯阪上 04/17 08:23
Blueshiva:之雲,不代表你就只能把每段話丟到Google翻譯剪下貼上交 04/17 08:24
Blueshiva:差了事 (當然如果你本來就是這種個性...那就算了) 04/17 08:24
Blueshiva:3.會寫的人不會在網路上玩?自己google一下zonble、高見 04/17 08:25
Blueshiva:龍、xdite,看他們夠不夠格稱得上"會寫",再看看他們有 04/17 08:26
Blueshiva:沒有在網路上"玩" 04/17 08:26
Blueshiva:4.找書?沒看置底文? 04/17 08:26
Blueshiva:5.最後回應一下為什麼書都在教沒有ARC的版本,因為ARC就 04/17 08:28
Blueshiva:只是自動加入retain/release,所以如果你真的要管好記憶 04/17 08:28
因為 MFC 只是自動加入 add ref count / remove ref count 所以也有助於理解 ARC 看,一樣說得通 要說不通就指出來: ARC 的 ref count 和 MFC 的做法不同 要不然,有用 ref count 的語言,其實也不只 C++/MFC 多得是觸類旁通的機會,做法也大同小異 我相信大部份人都因為過往的經驗而縮短了學習的時間
Blueshiva:體,了解沒有ARC的時候是怎麼運作的還是有相當大的幫助 04/17 08:28
Blueshiva:或者這樣講吧,把手動管理學起來,轉用ARC只是一篇簡單 04/17 08:29
Blueshiva:教學的事 04/17 08:29
我知道,所以我不可以發一篇 MFC 的作法來比較嗎? 我發了後,就是指責 Obj C '怎麼不用這種做法'嗎? 雖然我可以承認自己溝通有問題 但長此以往,再裝就不像了 除了謝謝指教,我還能說什麼?
howdiun:instruments裡面可以看各物件占用的記憶體 04/17 11:22
howdiun:記憶體吃太多,應該找出吃記憶體的物件 04/17 11:24
howdiun:加一減一那是知識,不是拿來實務用的,不知道也可以寫 04/17 11:25
剛和同事討論,同事還是用 memory leak 這個字眼 我稍微解釋一下後,他回我: 反正還不是一樣,都不正常 好啦,反正來回於兩個用字不同的群組間,就是要有一個人擔任翻譯 所以同事說 memory leak 時,我就自動翻譯成'記憶體佔用' ※ 編輯: HuangJC (60.251.197.63), 04/17/2014 15:12:15