电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

iOS內(nèi)存管理:從MRC到ARC實踐

瀏覽:68日期:2023-11-24 15:17:09

對于iOS程序員來說,內(nèi)存管理是入門的必修課。引用計數(shù)、自動釋放等概念,都是與C語言完全不同的。搞明白這些,代碼才有可能不crash。然而就是這么牛逼的內(nèi)存管理,著實讓我這個從 C 轉過來的老程序員頭疼了一段時間。

[C++ 程序員的迷惑和憤怒]

iOS 內(nèi)存管理的核心是引用計數(shù)。與眾多五年甚至更多以上開發(fā)經(jīng)驗的程序員一樣,筆者當初是從 C/C++轉到的 OC,接觸到 MRC。當時遇到最頭疼的問題就是:為什么那么多 release?到底什么地方會 release?同樣初始化一個字符串的兩個方法為什么不同?上邊一個不需要調用 release,后邊一個就需要調用 release?

NSString * str1 = [NSString stringWithFormat:”qqstock“]; NSString * str2 = [[NSString alloc] initWithData:recvData encoding:NSUTF8StringEncoding];

再加上一個屬性賦值與成員變量賦值,一個導致計數(shù)器加一,一個就不會!真他媽奇葩了!

self.name = @“qqstock”; _name = @“qqstock”;

不知道是不是所有從 C/C++ 轉過來的程序員都遇到過類似的迷惑和憤怒。

[MRC 的初衷和實現(xiàn)方式]

那么,蘋果為什么要做這個?

首先,C/C++ 傳統(tǒng)的內(nèi)存管理方式,所有的內(nèi)存都需要業(yè)務代碼自己處理,程序員自己一定要知道一個內(nèi)存對象什么時候不再使用了,一定要知道這個內(nèi)存對象的終點在哪里。當代碼越來越復雜,參與開發(fā)的程序員越來越多,甚至隨著歲月的流逝更換了新的程序員,這個時候,很難有人說的清了。于是,要么那個內(nèi)存對象一直留在那里,沒人敢釋放,整個程序占用的空間越來越大;要么,一個膽大的程序員將它釋放掉,某處發(fā)生了crash。盡管大家總結出許多類似“誰創(chuàng)建誰釋放”、“誰持有誰釋放” 的原則,但都導致存儲空間的浪費:為了保留僅僅一個內(nèi)存對象,卻要將與它關聯(lián)的一大堆對象保留住,而其中大部分已經(jīng)不再使用了。要么,自己寫許許多多的代碼,頻繁對容器進行主動操作。 iOS內(nèi)存管理:從MRC到ARC實踐

于是,蘋果要解決這個問題。初衷就是:任何一個內(nèi)存對象由系統(tǒng)自己處理釋放的問題,無論創(chuàng)建者也好,持有者也好,不需要去考慮別人是否還在使用同一個內(nèi)存對象,做好自己該做的就是了,別人的事情別人負責。蘋果實現(xiàn)此目的的手段就是引用計數(shù)。所有使用到同一內(nèi)存對象的地方,使用者只要保證自己 retain 一次,release 一次,就 OK 了,即便別人還在使用,你只要調用 release 將自己的引用次數(shù)清零就好了,不用管別人!

與 C/C++傳統(tǒng)的內(nèi)存管理方式相比,MRC 是不是顯得非常智能?是不是更加方便?而且,這樣做的代價也非常低廉,每一個內(nèi)存對象增加一個計數(shù)器就 OK 了,每一次 release,只需要檢查一遍計數(shù)器是否為零,如果為零就釋放,如果不為零就不執(zhí)行真正的釋放邏輯。

另外,為了解決函數(shù)返回值的問題,需要搞一個 autorelease 的東西,否則就會打破這個良好的初衷:“只負責自己范圍內(nèi)的事情就 OK了,不要管別人!”

那么,為什么不將所有內(nèi)存對象都統(tǒng)一成 retain呢?對于一種編譯器,它能夠用一個技術解決所有問題,就堅決不會用兩種并列的技術導致問題更復雜。

OC 有一個 delegate 的東西,這個東西的出現(xiàn)也是有其現(xiàn)實需求的,在此先跳過。如果所有地方都使用 retain,delegate 的問題一定會導致循環(huán)引用,除了 delegate,蘋果不敢保證所有用戶代碼的邏輯都是樹形結構的,最簡單的比如說循環(huán)鏈表、雙向鏈表,除此之外,業(yè)務層肯定也有某些地方必須做成“循環(huán)引用”,如果都是 retain,那么,最終處于循環(huán)中的內(nèi)存對象誰也不會被最終釋放掉。為了解決這個問題,蘋果依然保留了 C/C++的那種弱引用方式。——至少給程序員留個過渡的空間。

[MRC 的優(yōu)點和無奈]

總結一下:

MRC 的計數(shù)器機制改善了內(nèi)存管理的方式,減少了各個模塊的邏輯耦合,釋放了程序員對“何時該釋放”的心理壓力,解決了大部分的問題 為了應對各種復雜的場景,很無奈的留了一個口子; 兩種模式的并存,對 C++程序員轉移到 OC戰(zhàn)場,樹立了一個無形的心理門檻,使得起步階段問題更加復雜,比如:retain、assign、release、autorelease 等。

難道就沒有更好的方式么?當然有更好的方式,而且一定有許多公司的 C++程序員或者 C 程序員寫了類似引用計數(shù)的程序,甚至比引用計數(shù)還要高級,只不過大多數(shù)公司沒有實力推廣一個編程語言而已。

而且,略微深入思考,一定許多人想到:如果讓系統(tǒng)對所有內(nèi)存對象在運行時統(tǒng)一管理,問題就能徹底解決了。是的,的確如此,一定有人設計出來了。但是,代價比較高。

系統(tǒng)在運行時統(tǒng)一管理所有內(nèi)存對象的釋放,會導致增加額外的內(nèi)存和 CPU 開銷,在硬件設備尚且處于低級階段的時候,當程序員們依然在努力降低內(nèi)存降低 CPU 消耗的時候,推出這樣的機制,是不合時宜的!

引用計數(shù)器的方式,編譯器并沒有增加太多的邏輯,只是在創(chuàng)建的時候增加一個計數(shù)器,在釋放的時候編譯器自動幫程序員增加一個邏輯判斷。這個邏輯并沒有增加太多的內(nèi)存和 CPU 開銷。

再來看 autorelease,這個邏輯增加的成本可就大了去了,系統(tǒng)要一直持有該類型的內(nèi)存對象,直到本次 runloop 結束。所以,無論蘋果,還是有經(jīng)驗的程序員,都建議:能不用就盡量不用,能縮短范圍就盡量縮短范圍。 iOS內(nèi)存管理:從MRC到ARC實踐

[編程語言和編譯器的發(fā)展方向]

由于留了無奈的口子,野指針依然會出現(xiàn),該 crash 的時候依然 crash。許多人說:這是程序員的問題,如果代碼寫的足夠好,一定不會出現(xiàn)野指針,一定不會出現(xiàn) crash。是的,如果大家足夠小心,如果大家足夠盡力,這個世界上不會有任何沖突。

然而,編程語言和編譯器的發(fā)展,一定向著便利、易用、穩(wěn)健、職能,甚至傻瓜!如果一個編譯器能夠讓一個對計算機毫無了解的人一天之內(nèi)搞出自己想要的業(yè)務應用,誰又會拒絕呢?

許多程序員都是技術控,自己能做的事情盡量不讓別人做,自己能實現(xiàn)的邏輯盡量不用別人的。比如:C++的各種封裝、引用,我用 C 也能實現(xiàn),有什么大不了的!系統(tǒng)提供的各種類庫,我自己用底層的代碼也能實現(xiàn),而且性能更優(yōu),代碼更少!但是,如果你連一個磚頭都要自己燒制,連一堵墻都要自己去砌,其它更重要的事情誰去做?

更何況,人,總有打盹的時候。 iOS內(nèi)存管理:從MRC到ARC實踐

[ARC 的適時推出]

隨著硬件的升級,條件已經(jīng)成熟了,ARC到來了!

ARC 的初衷是為了讓程序員寫代碼的時候更加便利,最好不用再關注任何內(nèi)存釋放的問題(也不用關注用什么方式初始化的問題)。當然了,解決野指針的問題也是很重要的!總之,讓編碼更加簡單,程序更加健壯!

之前對 C++程序員頭疼的問題變得異常簡單:

NSString * str1 = [NSString stringWithFormat:”qqstock“];NSString * str2 = [[NSString alloc] initWithData:recvData encoding:NSUTF8StringEncoding];self.name = @“qqstock”; _name = @“qqstock”;

到底何時釋放?總之,你不用管了,用你的就好! 到底有何區(qū)別?沒啥區(qū)別,只管用就好了!

筆者之前一直很疑惑,因為自己一直想搞明白到底有何區(qū)別——技術控本質。現(xiàn)在,了解了ARC的初衷,也就敢于放心大膽的用了——許多刨根究底的程序員從匯編代碼也印證了這個“猜想”。ARC 的目的就是將程序員從 MRC 的各種”不同點“上解脫出來,對于尚未接觸過 MRC 的 C 程序員,是非常容易理解的,而對于已經(jīng)習慣了 MRC 的程序員,反倒有點”不敢相信“!

如果讓你做,你會如何實現(xiàn)?邏輯其實很簡單。 首先,強引用依然保留 MRC 的方式,因為這樣實現(xiàn)的方式代價很低; 其次,一旦出現(xiàn)弱引用,則將內(nèi)存對象在系統(tǒng)中建立映射表;一旦內(nèi)存對象因為所有強引用歸零而釋放,則將所有弱引用指針歸零(指向 nil)——應該有一個鏈表。

其實,將弱引用強制指向 nil,也是一種無奈的方式,按理說,這依然是個隱患,是代碼邏輯的缺陷,只是人家?guī)湍銓㈠e誤的代價降到最低而已。

總之,強引用的邏輯是:如果都不用了,我就釋放掉;弱引用的邏輯是:如果釋放了,我就置 nil!最終,程序員不需要關注內(nèi)存的持有和釋放問題,更不需要關注別的模塊是否依然在使用同一個內(nèi)存。做好自己分內(nèi)的事情,別的事情交給系統(tǒng)和編譯器! iOS內(nèi)存管理:從MRC到ARC實踐

[總結]

其實,筆者之前對 ARC 的了解也僅僅在 coding 層面,最近打算將老的項目從 MRC 轉到 ARC,需要提前讓團隊的所有人了解代碼如何遷移,否則即便依靠一兩個人的力量將代碼遷移了,開發(fā)人員的意識和 coding 依然停留在 MRC,那后續(xù)的開發(fā)任務將會極其危險。但凡做大的動作就應該首先在團隊層面無論是意識還是能力上做好準備,否則就等著填坑吧。

于是突發(fā)奇想,想對蘋果問一個為什么?即:蘋果為什么要搞一個 ARC?任何一件事情,都不是毫無來由的。一個極客程序員可能會突發(fā)奇想搞個牛逼的技術來展現(xiàn)自己的才華,但蘋果這么大一個公司,做這么大的改動,一定是有緣由的。果不其然,當自己費盡心思將這個問題搞清楚之后,如何 coding 的問題也得到了大幅提升!

回頭想想,這條路是很牛逼的,如果所有地方都用強引用,或者所有地方都交予系統(tǒng)管理,勢必會導致內(nèi)存的快速膨脹。某些其它語言的例子就非常明顯,無論程序員如何努力,內(nèi)存也很難降低下來。

一個心得就是:許多問題,如果我們能夠站在設計者的立場上考慮,就能夠更加清楚自己該如何 coding,設計者的初衷決定了我們 coding 的方式,設計者的 coding 決定了我們的思維方式。

以下是一個簡單的 demo,從代碼運行結果能夠很明顯的驗證 ARC 下 strong、weak、assign、局部變量、類方法初始化以及 autorelease 等使用方法與MRC下的不同。

首先:使用 retain 類型初始化方法給 weak 和 assign 類型變量賦值時,編譯器會報警。 iOS內(nèi)存管理:從MRC到ARC實踐

其次:weak 變量當其指向的變量的所有強引用置零后,自己會被置 nil,而 assign 卻不會。 iOS內(nèi)存管理:從MRC到ARC實踐

再有:weak 變量被置 nil,不是當其指向變量析構的時候,而是在強引用歸零的時候就已經(jīng)發(fā)生了。 iOS內(nèi)存管理:從MRC到ARC實踐 iOS內(nèi)存管理:從MRC到ARC實踐

還有,各種類方法初始化的 autorelease 對象,依然是在 runloop 結束的時候析構的,而 retain 類型的對象,卻是在代碼模塊終止的時候析構的。所以,出于內(nèi)存管理的考慮,依然建議少用 autorelease。 iOS內(nèi)存管理:從MRC到ARC實踐 iOS內(nèi)存管理:從MRC到ARC實踐

最后,strong 和 weak 對應的 set 方法,簡單了許多哦!

iOS內(nèi)存管理:從MRC到ARC實踐

來自:http://dev.qq.com/topic/59194943f473278853516915

標簽: IOS
相關文章:
主站蜘蛛池模板: 东莞注册公司-代办营业执照-东莞公司注册代理记账-极刻财税 | 上海软件开发-上海软件公司-软件外包-企业软件定制开发公司-咏熠科技 | 黑龙江「京科脑康」医院-哈尔滨失眠医院_哈尔滨治疗抑郁症医院_哈尔滨精神心理医院 | 座椅式升降机_无障碍升降平台_残疾人升降平台-南京明顺机械设备有限公司 | 美国PARKER齿轮泵,美国PARKER柱塞泵,美国PARKER叶片泵,美国PARKER电磁阀,美国PARKER比例阀-上海维特锐实业发展有限公司二部 | 山西3A认证|太原AAA信用认证|投标AAA信用证书-山西AAA企业信用评级网 | 长沙印刷厂-包装印刷-画册印刷厂家-湖南省日大彩色印务有限公司 青州搬家公司电话_青州搬家公司哪家好「鸿喜」青州搬家 | ?水马注水围挡_塑料注水围挡_防撞桶-常州瑞轩水马注水围挡有限公司 | 有机废气处理-rto焚烧炉-催化燃烧设备-VOC冷凝回收装置-三梯环境 | 上海公司注册-代理记账-招投标审计-上海昆仑扇财税咨询有限公司 上海冠顶工业设备有限公司-隧道炉,烘箱,UV固化机,涂装设备,高温炉,工业机器人生产厂家 | 数码听觉统合训练系统-儿童感觉-早期言语评估与训练系统-北京鑫泰盛世科技发展有限公司 | 北京公寓出租网-北京酒店式公寓出租平台 | 智能垃圾箱|垃圾房|垃圾分类亭|垃圾分类箱专业生产厂家定做-宿迁市传宇环保设备有限公司 | 焊缝跟踪系统_激光位移传感器_激光焊缝跟踪传感器-创想智控 | 施工电梯_齿条货梯_烟囱电梯_物料提升机-河南大诚机械制造有限公司 | 大通天成企业资质代办_承装修试电力设施许可证_增值电信业务经营许可证_无人机运营合格证_广播电视节目制作许可证 | bng防爆挠性连接管-定做金属防爆挠性管-依客思防爆科技 | 洗瓶机厂家-酒瓶玻璃瓶冲瓶机-瓶子烘干机-封口旋盖压盖打塞机_青州惠联灌装机械 | 我车网|我关心的汽车资讯_汽车图片_汽车生活! | 成人纸尿裤,成人尿不湿,成人护理垫-山东康舜日用品有限公司 | 广东风淋室_广东风淋室厂家_广东风淋室价格_广州开源_传递窗_FFU-广州开源净化科技有限公司 | 吸音板,隔音板,吸音材料,吸音板价格,声学材料 - 佛山诺声吸音板厂家 | 绿萝净除甲醛|深圳除甲醛公司|测甲醛怎么收费|培训机构|电影院|办公室|车内|室内除甲醛案例|原理|方法|价格立马咨询 | 大数据营销公司_舆情监测软件_上海SEO公司-文军营销官网 | 交变/复合盐雾试验箱-高低温冲击试验箱_安奈设备产品供应杭州/江苏南京/安徽马鞍山合肥等全国各地 | 武汉天安盾电子设备有限公司 - 安盾安检,武汉安检门,武汉安检机,武汉金属探测器,武汉测温安检门,武汉X光行李安检机,武汉防爆罐,武汉车底安全检查,武汉液体探测仪,武汉安检防爆设备 | 美能达分光测色仪_爱色丽分光测色仪-苏州方特电子科技有限公司 | 代理记账_免费注册公司_营业执照代办_资质代办-【乐财汇】 | 电缆接头-防爆电缆接头-格兰头-金属电缆接头-防爆填料函 | 丽陂特官网_手机信号屏蔽器_Wifi信号干扰器厂家_学校考场工厂会议室屏蔽仪 | 洗砂机械-球磨制砂机-洗沙制砂机械设备_青州冠诚重工机械有限公司 | 依维柯自动挡房车,自行式国产改装房车,小型房车价格,中国十大房车品牌_南京拓锐斯特房车 - 南京拓锐斯特房车 | 水厂自动化-水厂控制系统-泵站自动化|控制系统-闸门自动化控制-济南华通中控科技有限公司 | 送料机_高速冲床送料机_NC伺服滚轮送料机厂家-东莞市久谐自动化设备有限公司 | 网络推广公司_网络营销方案策划_企业网络推广外包平台-上海澜推网络 | 氢氧化钙设备_厂家-淄博工贸有限公司| 清水-铝合金-建筑模板厂家-木模板价格-铝模板生产「五棵松」品牌 | 集菌仪_智能集菌仪_全封闭集菌仪_无菌检查集菌仪厂家-那艾 | 自进式锚杆-自钻式中空注浆锚杆-洛阳恒诺锚固锚杆生产厂家 | 焊锡丝|焊锡条|无铅锡条|无铅锡丝|无铅焊锡线|低温锡膏-深圳市川崎锡业科技有限公司 | 卫生人才网-中国专业的医疗卫生医学人才网招聘网站! |