iOS面試題-內存管理

1.什么是 ARC瀑焦?

ARCiOS 5 引入的內存管理新功能 -- 自動引用計數(shù) 饥伊。它的工作原理大致是這樣:當我們編譯源碼時辅愿,編譯器會分析源碼中每個對象的生命周期竿报,然后基于這些對象的生命周期何吝,來添加相應的引用計數(shù)操作代碼溉委。所以,ARC 是工作在編譯期的一種技術方案爱榕。

這樣的好處是:編譯之后瓣喊,ARC 與非 MRC 代碼是沒有什么差別的,所以二者可以在源碼中共存黔酥。實際上藻三,你可以通過編譯參數(shù) -fno-objc-arc 來關閉部分源代碼的 ARC 特性。由于 ARC 能夠深度分析每一個對象的生命周期跪者,它能夠做到比 MRC 更加高效棵帽。

例如在一個函數(shù)中,對一個對象剛開始有一個引用計數(shù) +1 的操作渣玲,之后又緊接著有一個 -1 的操作逗概,那么編譯器就可以把這兩個操作都優(yōu)化掉。

2 ARC 的核心思想忘衍?
  • 自己生成的對象逾苫,自己持有
  • 非自己生成的對象,自己可以持有
  • 自己持有的對象不再需要時枚钓,需要對其進行釋放
  • 非自己持有的對象無法釋放
3 ARC 在使用時應該遵循的原則铅搓?
  • 不能使用 retainrelease搀捷、retainCount星掰、autorelease
  • 不可以使用 NSAllocateObject指煎、NSDeallocateObject蹋偏。
  • 必須遵守內存管理方法的命名規(guī)則便斥。
  • 不需要顯示的調用 Dealloc至壤。
  • 使用 @autoreleasePool 來代替 NSAutoreleasePool
  • 不可以使用區(qū)域 NSZone枢纠。
  • 對象性變量不可以作為 C 語言的結構體成員像街。
  • 顯示轉換 idvoid*黎棠。
4 ARC 在編譯時做了哪些工作?
  • 自動調用 保留(retain)釋放(release) 的方法
  • 相對于垃圾回收這類內存管理方案镰绎,ARC 不會帶來運行時的額外開銷脓斩,所以對于應用的運行效率不會有影響。 ARC 會把能夠互相抵消 retain畴栖、release随静、autorelease,操作簡化吗讶,如果發(fā)現(xiàn)在同一個對象上執(zhí)行了多次保留與釋放操作燎猛,那么 ARC 有時可以成對的移除這兩個操作。
5 ARC 在運行時做了哪些工作照皆?
  • 主要是指 weak 關鍵字重绷。weak 修飾的變量能夠在引用計數(shù)為0 時被自動設置成 nil,顯然是有運行時邏輯在工作的膜毁。關于原因會單獨開一個問題

  • 為了保證向后兼容性昭卓,ARC 在運行時檢測到類函數(shù)中的 autorelease 后緊跟其后 retain,此時不直接調用對象的 autorelease 方法瘟滨,而是改為調用 objc_autoreleaseReturnValue候醒。
    objc_autoreleaseReturnValue 會檢視當前方法返回之后即將要執(zhí)行的那段代碼,若那段代碼要在返回對象上執(zhí)行 retain 操作杂瘸,則設置全局數(shù)據(jù)結構中的一個標志位火焰,而不執(zhí)行 autorelease 操作,與之相似胧沫,如果方法返回了一個自動釋放的對象昌简,而調用方法的代碼要保留此對象,那么此時不直接執(zhí)行 retain 绒怨,而是改為執(zhí)行 objc_retainAoutoreleasedReturnValue函數(shù)纯赎。此函數(shù)要檢測剛才提到的標志位,若已經(jīng)置位南蹂,則不執(zhí)行 retain 操作犬金,設置并檢測標志位,要比調用 autoreleaseretain更快六剥。

_myPerson = [ECOPerson personWithName:@“Bob”]; 
ECOPerson * tmp = [ECOPerson personWithName:@“Bob”]; 
_myPerson = [tmp retain];
6 函數(shù)返回一個對象時晚顷,會對對象autorelease么?為什么疗疟?autorelease是什么時候釋放的该默?

會對對象 autorelease,因為需要在稍后釋放對象策彤,從而給調用者留下足夠長的時間栓袖,使其可以在需要時先保留返回值匣摘。此方法可以保證對象在跨越方法調用邊界時一定存活。

除非你有自己的自動釋放池裹刮,否則這個時機就是當前線程,當前事件循環(huán)結束時音榜,就是 RunLoop 結束時(observer -> beforeWaiting)。

// 情況一:
@autoreleasepool {
    NSObject * obj = [NSObject new];
    [obj autorelease];
    NSLog(@"%d",[obj retainCount]); //1
}
// 情況二:
NSObject * obj = [NSObject new];
[obj autorelease];
[obj autorelease];
NSLog(@"%d",[obj retainCount]); 
NSLog(@"%d",[obj retainCount]);   

// 崩潰
// 情況三:
NSObject * obj捧弃;
@autoreleasepool {
        obj = [NSObject new];
        [obj autorelease];
        NSLog(@"%d",[obj retainCount]);  // 1
  }
//crash  出了大括號就已經(jīng)被銷毀了
NSLog(@"%d",[obj retainCount]);
7 為什么已經(jīng)有了 ARC 赠叼,還需要 @autoreleasePool?

提到 OCRC违霞,首先要橫向對比一下 AndroidGC(垃圾回收機制)梅割,GC 的內存回收是集中式回收(定期回收),而 RC 的回收是伴隨整個運行時的葛家,所以 android 機器有種 時“卡”時“流暢” 的感覺户辞,而 iOS 總體比較均勻,缺乏像 GC 的集中式回收內存的類似機制癞谒,所以猜測 Pool的產(chǎn)生也是彌補 RC 的這一不足底燎,在 RC 基礎上進行內存優(yōu)化的一種手段。

8 簡要闡述內存相關的關鍵字弹砚?
Strong

Strong 修飾符表示指向并持有該對象双仍,其修飾對象的引用計數(shù)會加1。該對象只要引用計數(shù)不為0就不會被銷毀桌吃。當然可以通過將變量強制賦值 nil 來進行銷毀朱沃。

Weak

weak 修飾符指向但是并不持有該對象,引用計數(shù)也不會加1茅诱。在 Runtime 中對該屬性進行了相關操作逗物,無需處理,可以自動銷毀瑟俭。weak用來修飾對象翎卓,多用于避免循環(huán)引用的地方。weak 不可以修飾基本數(shù)據(jù)類型摆寄。

assign

assign主要用于修飾基本數(shù)據(jù)類型失暴,
例如NSIntegerCGFloat微饥,存儲在棧中逗扒,內存不用程序員管理。assign是可以修飾對象的欠橘,但是會出現(xiàn)問題矩肩。

copy

copy關鍵字和 strong類似,copy 多用于修飾有可變類型的不可變對象上 NSString,NSArray,NSDictionary上简软。

__unsafe_unretain

__unsafe_unretain 類似于 weak 蛮拔,但是當對象被釋放后,指針已然保存著之前的地址痹升,被釋放后的地址變?yōu)?僵尸對象建炫,訪問被釋放的地址就會出問題,所以說他是不安全的疼蛾。

__autoreleasing

將對象賦值給附有 __autoreleasing修飾的變量等同于 ARC 無效時調用對象的 autorelease 方法,實質就是扔進了自動釋放池肛跌。

9 說一下什么是懸垂指針?什么是野指針察郁?
懸垂指針

指針指向的內存已經(jīng)被釋放了衍慎,但是指針還存在,這就是一個 懸垂指針 或者說 迷途指針

野指針

沒有進行初始化的指針皮钠,其實都是 野指針

10 內存管理默認的關鍵字稳捆?
MRC
@property (atomic,readWrite,retain) NSString *name;
ARC
@property (atomic,readWrite,strong) NSString *name;
10 __weak 和 __unsafe_unretain 的區(qū)別精肃?

__weak__unsafe_unretain升級版揭绑,__unsafe_unretain 在指向的內存地址銷毀后,指針本身并不會自動銷毀征椒,這也就造成了野指針款侵,之后容易造成 Crash末荐。__weak 在指向的內存銷毀后,可以將指針變量置為 nil新锈,這樣更加安全甲脏。

11 __weak 修飾的變量在地址被釋放后,為何被置為 nil妹笆?

Runtime 中專門維護了一個用于存儲 weak指針變量的 weak 表块请,這實際上是一個 Hash 表。這個表 keyweak指針 所指向的內存地址拳缠,value 是指向這個內存地址的所有 weak指針负乡,實際上是一個數(shù)組。

過程可以總結為3步

  • 1脊凰、初始化時:runtime 會調用 objc_initWeak 函數(shù)抖棘,初始化一個新的 weak指針 指向對象的地址。
  • 2狸涌、添加引用時:objc_initWeak函數(shù)會調用 objc_storeWeak() 函數(shù)切省, objc_storeWeak()的作用是更新指針指向,創(chuàng)建對應的弱引用表帕胆。
  • 3朝捆、釋放時,調用 clearDeallocating 函數(shù)懒豹。clearDeallocating 函數(shù)首先根據(jù)對象地址獲取所有 weak指針 地址的數(shù)組芙盘,然后遍歷這個數(shù)組把其中的數(shù)據(jù)設為 nil驯用,最后把這個 entryweak表 中刪除,最后清理對象的記錄儒老。
12 為什么在 MRC 已經(jīng)有 __weak 的情況下蝴乔,還需要 _unsafe_unretain。驮樊?
  • 兼容性考慮薇正。iOS4 以及之前還沒有引入 weak,這種情況想表達弱引用的語義只能使用 unsafe_unretained囚衔。這種情況現(xiàn)在已經(jīng)很少見了挖腰。

  • 性能考慮。使用 weak 對性能有一些影響练湿,因此對性能要求高的地方可以考慮使用 unsafe_unretained 替換 weak猴仑。
    一個例子是 YYModel 的實現(xiàn),為了追求更高的性能肥哎,其中大量使用 unsafe_unretained 作為變量標識符宁脊。

13如何打破循環(huán)引用?
  • 注意變量作用域贤姆,使用 autorelease 讓編譯器來處理引用榆苞。
  • 使用弱引用(__weak)。
  • 當實例變量完成工作后霞捡,將其置為 nil坐漏。
14能不能用 assign 修飾 Nsobject 類型?

也可以碧信,但有可能出問題赊琳。

使用 assign 修飾 Nsobject 類型,賦值之后會被立即釋放砰碴,對應的屬性也就變成了野指針躏筏。

運行時跑到屬性有關操作會直接崩潰掉。

15 內存中的5大區(qū)都是什么呈枉?
  • 棧區(qū)(stack):由編譯器自動分配釋放 趁尼,存放函數(shù)的參數(shù)值,局部變量的值等猖辫。其 操作方式類似于數(shù)據(jù)結構中的棧酥泞。
  • 堆區(qū)(heap):一般由程序員分配釋放, 若程序員不釋放啃憎,程序結束時可能由OS回收 芝囤。注意它與數(shù)據(jù)結構中的堆是兩回事,分配方式倒是類似于鏈表。
  • 全局區(qū)(靜態(tài)區(qū))(static):全局變量和靜態(tài)變量的存儲是放在一塊的悯姊,初始化的 全局變量和靜態(tài)變量在一塊區(qū)域羡藐, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。 - 程序結束后由系統(tǒng)釋放悯许。
  • 文字常量區(qū):常量字符串就是放在這里的仆嗦。 程序結束后由系統(tǒng)釋放。
  • 程序代碼區(qū):存放函數(shù)體的二進制代碼岸晦。
16 autoReleasePool 什么時候釋放?

App啟動后欧啤,蘋果在主線程 RunLoop 里注冊了兩個 Observer睛藻,其回調都是 _wrapRunLoopWithAutoreleasePoolHandler()启上。

第一個 Observer 監(jiān)視的事件是 Entry(即將進入Loop),其回調內會調用 _objc_autoreleasePoolPush() 創(chuàng)建自動釋放池店印。其 order-2147483647冈在,優(yōu)先級最高,保證創(chuàng)建釋放池發(fā)生在其他所有回調之前按摘。

第二個 Observer 監(jiān)視了兩個事件: BeforeWaiting(準備進入休眠) 時調用_objc_autoreleasePoolPop()_objc_autoreleasePoolPush() 釋放舊的池并創(chuàng)建新池包券;Exit(即將退出Loop) 時調用 _objc_autoreleasePoolPop() 來釋放自動釋放池。這個 Observerorder2147483647炫贤,優(yōu)先級最低溅固,保證其釋放池子發(fā)生在其他所有回調之后。

在主線程執(zhí)行的代碼兰珍,通常是寫在諸如事件回調侍郭、Timer回調內的。這些回調會被 RunLoop 創(chuàng)建好的 AutoreleasePool 環(huán)繞著掠河,所以不會出現(xiàn)內存泄漏亮元,開發(fā)者也不必顯示創(chuàng)建 Pool 了。

17 簡要說一下自動引用計數(shù)的數(shù)據(jù)存儲結構唠摹?

可以參考這篇文章 : 黑幕背后的Autorelease

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末爆捞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子勾拉,更是在濱河造成了極大的恐慌煮甥,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件藕赞,死亡現(xiàn)場離奇詭異苛秕,居然都是意外死亡,警方通過查閱死者的電腦和手機找默,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門艇劫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事店煞⌒费荩” “怎么了?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵顷蟀,是天一觀的道長酒请。 經(jīng)常有香客問我,道長鸣个,這世上最難降的妖魔是什么羞反? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮囤萤,結果婚禮上昼窗,老公的妹妹穿的比我還像新娘。我一直安慰自己涛舍,他們只是感情好澄惊,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著富雅,像睡著了一般掸驱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上没佑,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天毕贼,我揣著相機與錄音,去河邊找鬼蛤奢。 笑死鬼癣,一個胖子當著我的面吹牛,可吹牛的內容都是我干的远剩。 我是一名探鬼主播扣溺,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瓜晤!你這毒婦竟也來了锥余?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤痢掠,失蹤者是張志新(化名)和其女友劉穎驱犹,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體足画,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡雄驹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了淹辞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片医舆。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出蔬将,到底是詐尸還是另有隱情爷速,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布霞怀,位于F島的核電站惫东,受9級特大地震影響,放射性物質發(fā)生泄漏毙石。R本人自食惡果不足惜廉沮,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望徐矩。 院中可真熱鬧滞时,春花似錦、人聲如沸丧蘸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽力喷。三九已至,卻和暖如春演训,著一層夾襖步出監(jiān)牢的瞬間弟孟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工样悟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拂募,地道東北人。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓窟她,卻偏偏與公主長得像陈症,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子震糖,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內容

  • Copyright ? 2017年ZaneWangWang. All rights reserved. 如果你看到...
    2897275c8a00閱讀 917評論 0 1
  • 1. 內總管理原則(引用計數(shù)) IOS的對象都繼承于NSObject, 該對象有一個方法:retainCount...
    lilinjianshu閱讀 2,156評論 0 2
  • # 前言 反復地復習iOS基礎知識和原理录肯,打磨知識體系是非常重要的,本篇就是重新溫習iOS的內存管理吊说。 內存管理是...
    Vein_閱讀 795評論 0 2
  • 文章結構 1.內存管理的基本規(guī)則2.autoreleasePool3.ARC管理方法3.1 ARC 引入的四個ow...
    leonardni閱讀 695評論 0 2
  • 每年年底都嚷嚷著要寫一篇轟轟烈烈的年終總結來證明自己這一年沒白活順帶為第二年大肆展望一番颁井,然而現(xiàn)實卻是每年都因為各...
    趙樂樂的雜貨鋪閱讀 573評論 0 0