iOS---內(nèi)存管理

筆者現(xiàn)在還是一個(gè)剛?cè)腴T iOS 開發(fā)的菜鳥邢滑,跟著部門的大佬在學(xué)習(xí)淳蔼。最近大佬讓我去了解一下 iOS 的內(nèi)存管理機(jī)制坷襟,然后寫一篇博文乡范。這篇博文主要都是從我的筆記中挑一些內(nèi)容來寫的配名,是從 ARC 下一直延伸相關(guān)的內(nèi)容,涉及的知識(shí)不是太全面晋辆。

ARC

  • ARC 是在編譯期時(shí)幫我們?cè)谶m當(dāng)?shù)牡胤饺ヌ砑庸芾硪糜?jì)數(shù)的代碼渠脉。Clang 編譯器中有一個(gè)叫“靜態(tài)分析器”(static analyzer),這個(gè)靜態(tài)分析器就會(huì)指明程序里引用計(jì)數(shù)出問題的地方瓶佳,然后告訴 ARC , ARC 就會(huì)自動(dòng)添加管理引用計(jì)數(shù)的代碼芋膘。
  • 還有一個(gè) ARC 優(yōu)化器,會(huì)幫我們?nèi)コ嘤嗟?release,retain語(yǔ)句
  • ARC下不能使用管理引用計(jì)數(shù)的代碼retain release autorelease dealloc
    直接調(diào)用上面的方法都會(huì)產(chǎn)生編譯錯(cuò)誤,原因是 ARC 在調(diào)用上面的方法時(shí)涩哟,不是通過普通的 Objc 消息派發(fā)機(jī)制索赏,而是直接調(diào)用底層的 C 語(yǔ)言版本。這樣做的原因是管理內(nèi)存的操作很頻繁贴彼,直接調(diào)用底層的函數(shù)可以節(jié)省 cpu 周期潜腻,性能會(huì)提高,而且也防止程序員手動(dòng)添加管理內(nèi)容的代碼而導(dǎo)致引用計(jì)數(shù)出現(xiàn)混亂的情況器仗,就算手動(dòng)添加內(nèi)存管理的代碼融涣,系統(tǒng)也不會(huì)去調(diào)用,它還是直接走底層的 C 語(yǔ)言函數(shù)精钮。

ARC下不用使autorelease威鹿,我們可以用autoreleasepool{}來替代,下面延伸的就是autoreleasepool轨香。

Autoreleasepool

autoreleasepool的結(jié)構(gòu)是怎么樣的呢忽你?<br />

autoreleasepool是由N個(gè)(至少一個(gè))autoreleasepoolpage(它的結(jié)構(gòu)是棧)相互連接的雙向鏈表。

1975281-0b868956aa0cf87c.png

看了幾遍博文臂容,理清了 autoreleasepool 內(nèi)部究竟是如何工作的科雳,我把大概的意思說一下。

@autoreleasepool{
    //代碼內(nèi)容脓杉,把捕捉到的對(duì)象都放到 autoreleasePool
}

實(shí)質(zhì)上糟秘,上面的調(diào)用了兩個(gè)方法,然后演變成下面的代碼

void * atautoreleasepool_obj = objc_autoreleasePoolPush();

        // 代碼內(nèi)容球散,把捉到的對(duì)象都放到autoreleasePool

        objc_autoreleasePoolPop(atautoreleasepool_obj);

因?yàn)?autoreleasePool 是由 autoreleasePoolPage 構(gòu)成的尿赚,所以自動(dòng)釋放池的PUSH 和 POP 都是由 autoreleasePoolPage 去 PUSH 和 POP
objc_autoreleasePoolPagePush
objc_autoreleasePoolPagePop

objc_autoreleasePoolPagePush里面又調(diào)用autoreleaseFast(POOL_SENTINEL)

先解釋一下POOL_SENTINEL(哨兵),這個(gè)東西可以說是一個(gè)清理標(biāo)志。我們把對(duì)象一個(gè)個(gè)往自動(dòng)釋放池里放凌净,也就是把對(duì)象一個(gè)個(gè)地往autoreleasePoolPage 進(jìn)棧悲龟,最后呢,我們?cè)谧詈筮M(jìn)棧那個(gè)位置+1泻蚊,放入POOL_SENTINEL躲舌。到了要 POP 的時(shí)候,給棧底到POOL_SENTINEL之間的對(duì)象 release性雄。

PUSH的具體做法(也就是autoreleaseFast這個(gè)方法要做的事情)

拿到一個(gè)當(dāng)前 autoreleasePoolPage 對(duì)象 page

  1. 如果page存在没卸,而且不是滿的,那就把對(duì)象進(jìn)去
  2. `page 存在秒旋,但是滿的约计。新建一個(gè) page,設(shè)置好父子指針迁筛,添加對(duì)象
  3. page不存在煤蚌,那就創(chuàng)建一個(gè),添加對(duì)象<br />

POP 的具體做法

  1. 拿到當(dāng)前的所在的 Page 對(duì)象
  2. 調(diào)用releaseUntil把對(duì)象 release(這時(shí)用到剛剛說的POOL_SENTINEL
  3. kill掉已經(jīng)被清空的子 Page

autoreleasePool 應(yīng)該在什么時(shí)候去使用

  1. 寫基于命令行的程序细卧,就是沒有 UI 框架的時(shí)候尉桩。(這種情況我還得找找資料再做解釋)
  2. 在循環(huán)中創(chuàng)建了大量的臨時(shí)對(duì)象。
for(int i = 0; i < 10000 ;i ++){
  autoreleasepool{
       //創(chuàng)建一些臨時(shí)對(duì)象去搞事情
}
}

在循環(huán)內(nèi)部加上 autoreleasepool 贪庙,每一次循環(huán)結(jié)束后蜘犁,那些臨時(shí)的對(duì)象就被釋放掉,不用等到全部的循環(huán)都結(jié)束掉止邮,再去一次釋放这橙,這樣就避免了程序的內(nèi)存一直飆升,到最后一下子又降下來的情況导披。

  1. 在子線程中需要自動(dòng)創(chuàng)建屈扎。
    主線程的 autoreleasepool 是系統(tǒng)幫我們創(chuàng)建好的,但是子線程時(shí)沒有創(chuàng)建的撩匕,所以我們要?jiǎng)?chuàng)建鹰晨。runloop 也是一樣,在子線程中止毕,需要我們自己去創(chuàng)建模蜡。

AutoreleasePool 和 RunLoop 的關(guān)系

  1. 在 RunLoop 創(chuàng)建之前,會(huì) PUSH 一個(gè)自動(dòng)釋放池
  2. 在 RunLoop 睡眠時(shí)滓技,會(huì) POP 自動(dòng)釋放池(這個(gè)就解釋放在自動(dòng)釋放池的對(duì)象時(shí)什么時(shí)候釋放的,跟 RunLoop 是密切相關(guān)的)棚潦,然后又 PUSH 一個(gè)新的自動(dòng)釋放池( RunLoop 有可能重新被喚醒工作令漂,所以我們像第一步那樣,在 RunLoop 工作前,創(chuàng)建好自動(dòng)釋放池)
  3. RunLoop 退出時(shí)叠必,POP 掉最后的那個(gè)自動(dòng)釋放池

其實(shí)還有很多關(guān)于 iOS 內(nèi)存管理的知識(shí)荚孵,之后我會(huì)繼續(xù)補(bǔ)充。這個(gè)是筆者的第一篇博文纬朝,如果發(fā)現(xiàn)博文有錯(cuò)誤的地方收叶,請(qǐng)各位讀者指出來,筆者會(huì)慢慢修正共苛。

我也會(huì)繼續(xù)跟著我們部門的大佬學(xué)習(xí)判没,慢慢掌握更多 iOS 的知識(shí),分享更多的博文隅茎。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末澄峰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子辟犀,更是在濱河造成了極大的恐慌俏竞,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件堂竟,死亡現(xiàn)場(chǎng)離奇詭異魂毁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)出嘹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門席楚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人疚漆,你說我怎么就攤上這事酣胀。” “怎么了娶聘?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵闻镶,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我丸升,道長(zhǎng)铆农,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任狡耻,我火速辦了婚禮墩剖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘夷狰。我一直安慰自己岭皂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布沼头。 她就那樣靜靜地躺著爷绘,像睡著了一般书劝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上土至,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天购对,我揣著相機(jī)與錄音,去河邊找鬼陶因。 笑死骡苞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的楷扬。 我是一名探鬼主播解幽,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼毅否!你這毒婦竟也來了亚铁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤螟加,失蹤者是張志新(化名)和其女友劉穎徘溢,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捆探,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡然爆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了黍图。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片曾雕。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖助被,靈堂內(nèi)的尸體忽然破棺而出剖张,到底是詐尸還是另有隱情,我是刑警寧澤揩环,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布搔弄,位于F島的核電站,受9級(jí)特大地震影響丰滑,放射性物質(zhì)發(fā)生泄漏顾犹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一褒墨、第九天 我趴在偏房一處隱蔽的房頂上張望炫刷。 院中可真熱鬧,春花似錦郁妈、人聲如沸浑玛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)顾彰。三九已至失晴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拘央,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工书在, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留灰伟,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓儒旬,卻偏偏與公主長(zhǎng)得像栏账,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子栈源,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容