可能碰到的iOS筆試面試題(6)--內(nèi)存管理

內(nèi)存管理

ARC處理原理

ARC是Objective-C編譯器的特性,而不是運(yùn)行時(shí)特性或者垃圾回收機(jī)制躁倒,ARC所做的只不過(guò)是在代碼編譯時(shí)為你自動(dòng)在合適的位置插入release或autorelease琉雳,只要沒(méi)有強(qiáng)指針指向?qū)ο螅瑢?duì)象就會(huì)被釋放。

  • 前端編譯器

前端編譯器會(huì)為“擁有的”每一個(gè)對(duì)象插入相應(yīng)的release語(yǔ)句税手。如果對(duì)象的所有權(quán)修飾符是__strong,那么它就是被擁有的需纳。如果在某個(gè)方法內(nèi)創(chuàng)建了一個(gè)對(duì)象芦倒,前端編譯器會(huì)在方法末尾自動(dòng)插入release語(yǔ)句以銷(xiāo)毀它。而類(lèi)擁有的對(duì)象(實(shí)例變量/屬性)會(huì)在dealloc方法內(nèi)被釋放不翩。事實(shí)上兵扬,你并不需要寫(xiě)dealloc方法或調(diào)用父類(lèi)的dealloc方法,ARC會(huì)自動(dòng)幫你完成一切口蝠。此外器钟,由編譯器生成的代碼甚至?xí)饶阕约簩?xiě)的release語(yǔ)句的性能還要好,因?yàn)榫庉嬈骺梢宰鞒鲆恍┘僭O(shè)妙蔗。在ARC中俱箱,沒(méi)有類(lèi)可以覆蓋release方法,也沒(méi)有調(diào)用它的必要灭必。ARC會(huì)通過(guò)直接使用objc_release來(lái)優(yōu)化調(diào)用過(guò)程狞谱。而對(duì)于retain也是同樣的方法乃摹。ARC會(huì)調(diào)用objc_retain來(lái)取代保留消息。

  • ARC優(yōu)化器

雖然前端編譯器聽(tīng)起來(lái)很厲害的樣子跟衅,但代碼中有時(shí)仍會(huì)出現(xiàn)幾個(gè)對(duì)retain和release的重復(fù)調(diào)用孵睬。ARC優(yōu)化器負(fù)責(zé)移除多余的retain和release語(yǔ)句,確保生成的代碼運(yùn)行速度高于手動(dòng)引用計(jì)數(shù)的代碼伶跷。

下面關(guān)于Objective-C內(nèi)存管理的描述錯(cuò)誤的是

A 當(dāng)使用ARC來(lái)管理內(nèi)存時(shí)掰读,代碼中不可以出現(xiàn)autorelease
B autoreleasepool 在 drain 的時(shí)候會(huì)釋放在其中分配的對(duì)象
C 當(dāng)使用ARC來(lái)管理內(nèi)存時(shí),在線(xiàn)程中大量分配對(duì)象而不用autoreleasepool則可能會(huì)造成內(nèi)存泄露
D 在使用ARC的項(xiàng)目中不能使用NSZone
  • 參考答案:A
  • 理由:ARC只是在大多時(shí)候編譯自動(dòng)為我們添加上內(nèi)存管理的代碼叭莫,只是我們的源代碼看不到而已蹈集,但是在編譯時(shí),編譯器會(huì)添加上相關(guān)內(nèi)存管理代碼雇初。對(duì)于自動(dòng)釋放池拢肆,在drain時(shí)會(huì)將自動(dòng)釋放池中的所有對(duì)象的引用計(jì)數(shù)減一,若引用計(jì)數(shù)為0靖诗,則會(huì)自動(dòng)釋放掉其內(nèi)存郭怪。如果在線(xiàn)程中需要大量分配內(nèi)存,我們理應(yīng)添加上自動(dòng)釋放池刊橘,以防內(nèi)存泄露鄙才。比如在for循環(huán)中要分配大量的內(nèi)存處理數(shù)據(jù),那么我們應(yīng)該在for循環(huán)內(nèi)添加自動(dòng)釋放池促绵,在每個(gè)循環(huán)后就將內(nèi)存釋放掉攒庵,防止內(nèi)存泄露。在ARC項(xiàng)目中败晴,自然不能手動(dòng)使用NSZone浓冒,也不能調(diào)用父類(lèi)的dealloc。

MRC文件在ARC工程混合編譯時(shí)位衩,需要在文件的Compiler Flags上添加什么參數(shù)

A -shared
B -fno-objc-arc
C -fobjc-arc
D -dynamic
參考答案:B

什么情況使用 weak 關(guān)鍵字裆蒸,相比 assign 有什么不同?

  • 什么情況使用weak關(guān)鍵字?
  • 在 ARC 中,在有可能出現(xiàn)循環(huán)引用的時(shí)候,往往要通過(guò)讓其中一端使用 weak 來(lái)解決,比如: delegate 代理屬性
    自身已經(jīng)對(duì)它進(jìn)行一次強(qiáng)引用,沒(méi)有必要再?gòu)?qiáng)引用一次,此時(shí)也會(huì)使用 weak,自定義 IBOutlet 控件屬性一般也使用 weak糖驴;當(dāng)然僚祷,也可以使用strong。
  • weak與assign的不同?
  • weak 此特質(zhì)表明該屬性定義了一種“非擁有關(guān)系” (nonowning relationship)贮缕。為這種屬性設(shè)置新值時(shí)辙谜,設(shè)置方法既不保留新值,也不釋放舊值感昼。此特質(zhì)同assign類(lèi)似装哆, 然而在屬性所指的對(duì)象遭到摧毀時(shí),屬性值也會(huì)清空(nil out)。 而 assign 的“設(shè)置方法”只會(huì)執(zhí)行針對(duì)“純量類(lèi)型” (scalar type蜕琴,例如 CGFloat 或 NSlnteger 等)的簡(jiǎn)單賦值操作萍桌。
  • assigin 可以用非 OC 對(duì)象,而 weak 必須用于 OC 對(duì)象

調(diào)用對(duì)象的release 方法會(huì)銷(xiāo)毀對(duì)象嗎?

    不會(huì)凌简,調(diào)用對(duì)象的release 方法只是將對(duì)象的引用計(jì)數(shù)器-1上炎,當(dāng)對(duì)象的引用計(jì)數(shù)器為0的時(shí)候會(huì)調(diào)用了對(duì)象的dealloc 方法才能進(jìn)行釋放對(duì)象的內(nèi)存。

自動(dòng)釋放池常見(jiàn)面試代碼

for (int i = 0; i < someLargeNumber; ++i)
{   
    NSString *string = @"Abc";
    string = [string lowercaseString];
    string = [string stringByAppendingString:@"xyz"]; 
    NSLog(@"%@",string);
}

問(wèn):以上代碼存在什么樣的問(wèn)題雏搂?如果循環(huán)的次數(shù)非常大時(shí)藕施,應(yīng)該如何修改?

存在問(wèn)題:?jiǎn)栴}處在每執(zhí)行一次循環(huán)凸郑,就會(huì)有一個(gè)string加到當(dāng)前runloop中的自動(dòng)釋放池中裳食,只有當(dāng)自動(dòng)釋放池被release的時(shí)候,自動(dòng)釋放池中的標(biāo)示了autorelease的這些數(shù)據(jù)所占用的內(nèi)存空間才能被釋放掉芙沥。假設(shè)诲祸,當(dāng)someLargeNumber大到一定程度時(shí),內(nèi)存空間將被耗盡而沒(méi)有被釋放掉憨愉,所以就出現(xiàn)了內(nèi)存溢出的現(xiàn)象烦绳。

解決辦法1:如果i比較大卿捎,可以用@autoreleasepool {}解決配紫,放在for循環(huán)外,循環(huán)結(jié)束后午阵,銷(xiāo)毀創(chuàng)建的對(duì)象躺孝,解決占據(jù)棧區(qū)內(nèi)存的問(wèn)題

解決方法2:如果i玩命大,一次循環(huán)都會(huì)造成自動(dòng)釋放池被填滿(mǎn)底桂,自動(dòng)釋放池放在for循環(huán)內(nèi)植袍,每次循環(huán)都將上一次創(chuàng)建的對(duì)象release
修改之后:
for(int i = 0; i<1000;i++){
NSAutoreleasePool * pool1 = [[NSAutoreleasePool alloc] init]; 
NSString *string = @"Abc";
string = [string lowercaseString];
string = [string stringByAppendingString:@"xyz"]; 
NSLog(@"%@",string);
//釋放池
[pool1 drain]; }

objective-C對(duì)象的內(nèi)存布局是怎樣的?

  • 由于Objective-C中沒(méi)有多繼承籽懦,因此其內(nèi)存布局還是很簡(jiǎn)單的于个,就是:最前面有個(gè)isa指針,然后父類(lèi)的實(shí)例變量存放在子類(lèi)的成員變量之前

看下面的程序,第一個(gè)NSLog會(huì)輸出什么?這時(shí)str的retainCount是多少?第二個(gè)和第三個(gè)呢? 為什么?

NSMutableArray* ary = [[NSMutableArray array] retain];
NSString *str = [NSString stringWithFormat:@"test"];
[str retain];
[aryaddObject:str];
NSLog(@”%@%d”,str,[str retainCount]);
[str retain];
[str release];
[str release];
NSLog(@”%@%d”,str,[str retainCount]);
[aryremoveAllObjects]
NSLog(@”%@%d”,str,[str retainCount]);
str的retainCount創(chuàng)建+1暮顺,retain+1厅篓,加入數(shù)組自動(dòng)+1 3
retain+1,release-1捶码,release-1 2
數(shù)組刪除所有對(duì)象羽氮,所有數(shù)組內(nèi)的對(duì)象自動(dòng)-1 1

回答person的retainCount值,并解釋為什么

Person * per = [[Person alloc] init]; 此時(shí)person 的retainCount的值是1 self.person = per;
在self.person 時(shí),如果是assign,person的 retainCount的值不變,仍為1 若是:retain person的retainCount的值加1,變?yōu)?
若是:copy person的retainCount值不變,仍為1

什么時(shí)候需要在程序中創(chuàng)建內(nèi)存池?

  • 用戶(hù)自己創(chuàng)建的數(shù)據(jù)線(xiàn)程,則需要?jiǎng)?chuàng)建該線(xiàn)程的內(nèi)存池

如果我們不創(chuàng)建內(nèi)存池惫恼,是否有內(nèi)存池提供給我們?

  • 界面線(xiàn)程維護(hù)著自己的內(nèi)存池档押,用戶(hù)自己創(chuàng)建的數(shù)據(jù)線(xiàn)程,則需要?jiǎng)?chuàng)建該線(xiàn)程的內(nèi)存池

蘋(píng)果是如何實(shí)現(xiàn)autoreleasepool的?

autoreleasepool以一個(gè)隊(duì)列數(shù)組的形式實(shí)現(xiàn),主要通過(guò)下列三個(gè)函數(shù)完成.
?   objc_autoreleasepoolPush
?   objc_autoreleasepoolPop
?   objc_autorelease
看函數(shù)名就可以知道令宿,對(duì)autorelease分別執(zhí)行push叼耙、pop操作。銷(xiāo)毀對(duì)象時(shí)執(zhí)行release操作粒没。

objc使用什么機(jī)制管理對(duì)象內(nèi)存旬蟋?

  • 通過(guò)引用計(jì)數(shù)器(retainCount)的機(jī)制來(lái)決定對(duì)象是否需要釋放。 每次runloop完成一個(gè)循環(huán)的時(shí)候革娄,都會(huì)檢查對(duì)象的 retainCount倾贰,如果retainCount為0,說(shuō)明該對(duì)象沒(méi)有地方需要繼續(xù)使用了拦惋,可以釋放掉了匆浙。

為什么要進(jìn)行內(nèi)存管理?

  • 因?yàn)橐苿?dòng)設(shè)備的內(nèi)存極其有限,當(dāng)一個(gè)程序所占內(nèi)存達(dá)到一定值時(shí), 系統(tǒng)會(huì)發(fā)出內(nèi)存警告. 當(dāng)程序達(dá)到更大的值時(shí), 程序會(huì)閃退, 影響用戶(hù)體驗(yàn). 為了保證程序的運(yùn)行流暢, 必須進(jìn)行內(nèi)存管理

內(nèi)存管理的范圍?

  • 管理所有繼承自NSObject的對(duì)象, 對(duì)基本數(shù)據(jù)類(lèi)型無(wú)效.是因?yàn)閷?duì)象和其他數(shù)據(jù)類(lèi)型在系統(tǒng)中存儲(chǔ)的空間不一樣,其他局部變量主要存儲(chǔ)在棧區(qū)(因?yàn)榛緮?shù)據(jù)類(lèi)型占用的存儲(chǔ)空間是固定的,一般存放于棧區(qū)),而對(duì)象存儲(chǔ)于堆中,當(dāng)代碼塊結(jié)束時(shí),這個(gè)代碼塊所涉及到的所有局部變量會(huì)自動(dòng)彈棧清空,指向?qū)ο蟮闹羔樢矔?huì)被回收,這時(shí)對(duì)象就沒(méi)有指針指向,但依然存在于堆內(nèi)存中,造成內(nèi)存泄露.

objc使用什么機(jī)制管理對(duì)象內(nèi)存(或者內(nèi)存管理方式有哪些)厕妖?(重點(diǎn))

  • MRC(manual retain-release)手動(dòng)內(nèi)存管理
  • ARC(automatic reference counting)自動(dòng)引用計(jì)數(shù)
  • Garbage collection (垃圾回收)首尼。但是iOS不支持垃圾回收, ARC作為L(zhǎng)LVM3.0編譯器的一項(xiàng)特性, 在iOS5.0 (Xcode4) 版本后推出的。
  • ARC的判斷準(zhǔn)則, 只要沒(méi)有強(qiáng)指針指向?qū)ο? 對(duì)象就會(huì)被釋放.

iOS是如何管理內(nèi)存的言秸?

  • 這個(gè)問(wèn)題的話(huà)上一個(gè)問(wèn)題也提到過(guò),講下block的內(nèi)存管理,ARC下的黃金法則就行软能。

  • 這里說(shuō)下swift里的內(nèi)存管理:
    delgate照樣weak修飾,閉包前面用[weak self],swift里的新東西,unowned,舉例,如果self在閉包被調(diào)用的時(shí)候可能為空,則用weak,反之亦然,如果為空時(shí)使用了unowned,程序會(huì)崩潰,類(lèi)似訪(fǎng)問(wèn)了懸掛指針,在oc中類(lèi)似于unsafe_unretained,類(lèi)似assign修飾了oc對(duì)象,對(duì)象被銷(xiāo)毀后,被unowned修飾的對(duì)象不會(huì)為空,但是unowned訪(fǎng)問(wèn)速度更快,因?yàn)閣eak需要unwarp后才能使用

內(nèi)存管理的原則

  • 只要還有人在使用這個(gè)對(duì)象, 那么這個(gè)對(duì)象就不會(huì)被回收
  • 只有你想使用這個(gè)對(duì)象, 那么就應(yīng)該讓這個(gè)對(duì)象的引用計(jì)數(shù)器加1
  • 當(dāng)你不想使用這個(gè)對(duì)象時(shí), 應(yīng)該讓對(duì)象的引用計(jì)數(shù)器減1
  • 誰(shuí)創(chuàng)建, 就由誰(shuí)來(lái)release
    • 如果你通過(guò)alloc, new, copy 來(lái)創(chuàng)建一個(gè)對(duì)象, 當(dāng)你不想用這個(gè)對(duì)象的時(shí)候就必須調(diào)用release 或者autorelease 讓引用計(jì)數(shù)器減1
    • 不是你創(chuàng)建的就不用你負(fù)責(zé) release
  • 誰(shuí)retain 誰(shuí)release
    • 只要你調(diào)用了retain ,無(wú)論這個(gè)對(duì)象如何生成, 都需要調(diào)用release
  • 總結(jié):
    有加就應(yīng)該有減, 曾讓某個(gè)計(jì)數(shù)器加1, 就應(yīng)該讓其在最后減1

內(nèi)存管理研究的對(duì)象:

  • 野指針:指針變量沒(méi)有進(jìn)行初始化或指向的空間已經(jīng)被釋放。

    • 使用野指針調(diào)用對(duì)象方法举畸,會(huì)報(bào)異常查排,程序崩潰。
    • 通常再調(diào)用完release方法后抄沮,把保存對(duì)象指針的地址清空跋核,賦值為nil,找oc中沒(méi)有空指針異常叛买,所以[nil retain]調(diào)用方法不會(huì)有異常砂代。
  • 內(nèi)存泄露

    • 如 Person * person = [Person new]; (對(duì)象提前賦值nil或者清空)在棧區(qū)的person已經(jīng)被釋放, 而堆區(qū)new產(chǎn)生的對(duì)象還沒(méi)有釋放, 就會(huì)造成內(nèi)存泄露
    • 在MRC手動(dòng)引用計(jì)數(shù)器模式下, 造成內(nèi)存泄露的情況
      1. 沒(méi)有配對(duì)釋放,不符合內(nèi)存管理原則
      2. 對(duì)象提前賦值nil或者清空率挣,導(dǎo)致release不起作用刻伊。
  • 僵尸對(duì)象 : 堆中已經(jīng)被釋放的對(duì)象(retainCount = 0)

  • 空指針 : 指針賦值為空,nil

如何判斷對(duì)象已經(jīng)被銷(xiāo)毀

  • 重寫(xiě)dealloc方法,對(duì)象銷(xiāo)毀時(shí)椒功,會(huì)調(diào)用捶箱,重寫(xiě)時(shí)一定要[super dealloc]

retainCount = 0,使用retain能否復(fù)活對(duì)象

  • 已經(jīng)被釋放的對(duì)象無(wú)法復(fù)活

對(duì)象與對(duì)象之間存在的關(guān)系

  1. 繼承關(guān)系
  2. 組合關(guān)系(是一種強(qiáng)烈的包含關(guān)系)
  3. 依賴(lài)關(guān)系(對(duì)象作為方法參數(shù)傳遞)

對(duì)象的組合關(guān)系中蛾茉,確保成員變量不被提前釋放讼呢?

  • 重寫(xiě)set方法,在set方法中谦炬,retain該對(duì)象悦屏。

成員變量的對(duì)象节沦,在哪里配對(duì)釋放?

  • dealloc中釋放

對(duì)象組合關(guān)系中础爬,內(nèi)存泄露有哪幾種情況甫贯?

  • set方法沒(méi)有retain對(duì)象
  • 沒(méi)有release舊對(duì)象
  • 沒(méi)有判斷向set方法中傳入的是否為同一個(gè)對(duì)象

正確重寫(xiě)set方法

  • 判斷是否為同一對(duì)象
  • release舊對(duì)象
  • retain新對(duì)象

分別描述內(nèi)存管理要點(diǎn)、autorelease看蚜、release叫搁、NSAutoreleasePool?并說(shuō)明autorelease是什么時(shí)候被release的?簡(jiǎn)述什么時(shí)候由你負(fù)責(zé)釋放對(duì)象,什么時(shí)候不由你釋放?[NSAutoreleasePool release]和[NSAutoreleasePool drain]有什么區(qū)別?

  • 內(nèi)存管理要點(diǎn):Objective-C 使用引用計(jì)數(shù)機(jī)制(retainCount)來(lái)管理內(nèi)存。

  • 內(nèi)存每被引用一次,該內(nèi)存的引用計(jì)數(shù)+1,每被釋放一次引 用計(jì)數(shù)-1供炎。

  • 當(dāng)引用計(jì)數(shù) = 0 的時(shí)候,調(diào)用該對(duì)象的 dealloc 方法,來(lái)徹底從內(nèi)存中刪除該對(duì)象渴逻。

  • alloc,allocWithZone,new(帶初始化)時(shí):該對(duì)象引用計(jì)數(shù) +1;

  • retain:手動(dòng)為該對(duì)象引用計(jì)數(shù) +1;

  • copy:對(duì)象引用計(jì)數(shù) +1;//注意copy的OC數(shù)據(jù)類(lèi)型是否有mutable,如有為深拷貝音诫,新對(duì)象計(jì)數(shù)為1惨奕,如果沒(méi)有,為淺拷貝竭钝,計(jì)數(shù)+1

  • mutableCopy:生成一個(gè)新對(duì)象,新對(duì)象引用計(jì)數(shù)為 1;

  • release:手動(dòng)為該對(duì)象引用計(jì)數(shù) -1;

  • autorelease:把該對(duì)象放入自動(dòng)釋放池,當(dāng)自動(dòng)釋放池釋放時(shí),其內(nèi)的對(duì)象引用計(jì)數(shù) -1梨撞。

  • NSAutoreleasePool: NSAutoreleasePool是通過(guò)接收對(duì)象向它發(fā)送的autorelease消息,記錄該對(duì)象的release消息,當(dāng)自動(dòng)釋放池被銷(xiāo)毀時(shí),會(huì)自動(dòng)向池中的對(duì)象發(fā)送release消息。

  • autorelease 是在自動(dòng)釋放池被銷(xiāo)毀,向池中的對(duì)象發(fā)送release
    只能釋放自己擁有的對(duì)象香罐。

  • 區(qū)別是:在引用計(jì)數(shù)環(huán)境下(在不使用ARC情況下),兩者基本一樣,在GC(垃圾回收制)環(huán)境下,release 是一個(gè)no-op(無(wú)效操作),所以無(wú)論是不是GC都使用drain

  • 面試中內(nèi)存管理,release和autorelease的含義?這里尤其要強(qiáng)調(diào)下autorelease,它引申出自動(dòng)釋放池,也能引申出Run loop!

自動(dòng)釋放池是什么,如何工作 ?

  • 什么是自動(dòng)釋放池:用來(lái)存儲(chǔ)多個(gè)對(duì)象類(lèi)型的指針變量
  • 自動(dòng)釋放池對(duì)池內(nèi)對(duì)象的作用:存入池內(nèi)的對(duì)象卧波,當(dāng)自動(dòng)釋放池被銷(xiāo)毀時(shí),會(huì)對(duì)池內(nèi)對(duì)象全部做一次release操作
  • 對(duì)象如何加入池中:調(diào)用對(duì)象的autorelease方法
  • 自動(dòng)釋放池能嵌套使用嗎:能
  • 自動(dòng)釋放池何時(shí)被銷(xiāo)毀 :簡(jiǎn)單的看庇茫,autorelease的"}"執(zhí)行完以后港粱。而實(shí)際情況是Autorelease對(duì)象是在當(dāng)前的runloop迭代結(jié)束時(shí)釋放的,而它能夠釋放的原因是系統(tǒng)在每個(gè)runloop迭代中都加入了自動(dòng)釋放池Push和Pop
  • 多次調(diào)用對(duì)象的autorelease方法會(huì)導(dǎo)致:野指針異常
  • 自動(dòng)釋放池的作用:將對(duì)象與自動(dòng)釋放池建立關(guān)系港令,池子內(nèi)調(diào)用autorelease啥容,在自動(dòng)釋放池銷(xiāo)毀時(shí)銷(xiāo)毀對(duì)象锈颗,延遲release銷(xiāo)毀時(shí)間

自動(dòng)釋放池什么時(shí)候釋放顷霹?

  • 通過(guò)Observer監(jiān)聽(tīng)RunLoop的狀態(tài),一旦監(jiān)聽(tīng)到RunLoop即將進(jìn)入睡眠等待狀態(tài)击吱,就釋放自動(dòng)釋放池(kCFRunLoopBeforeWaiting)

IPhone OS有沒(méi)有垃圾回收?autorelease 和垃圾回收制(gc)有什么關(guān)系?

  • iOS 中沒(méi)有垃圾回收淋淀。autorelease只是延遲釋放,gc是每隔一段時(shí)間詢(xún)問(wèn)程序,看是否有無(wú)指針指向的對(duì)象,若有,就將它回收。他們兩者沒(méi)有什么關(guān)系覆醇。

ARC問(wèn)題

  1. 什么是arc機(jī)制:自動(dòng)引用計(jì)數(shù).
  2. 系統(tǒng)判斷對(duì)象是否銷(xiāo)毀的依據(jù):指向?qū)ο蟮膹?qiáng)指針是否被銷(xiāo)毀
  3. arc的本質(zhì):對(duì)retainCount計(jì)算朵纷,創(chuàng)建+1 清空指針 - 1 或者到達(dá)autoreleasepool的大括號(hào)-1
  4. arc目的:不需要程序員關(guān)心retain和release操作.
  5. 如何解決arc機(jī)制下類(lèi)的相互引用:.h文件中使用@class關(guān)鍵字聲明一個(gè)類(lèi),兩端不能都用強(qiáng)指針永脓,一端用strong一端用weak

ARC通過(guò)什么方式幫助開(kāi)發(fā)者管理內(nèi)存袍辞?

ARC相對(duì)于MRC,不是在編譯時(shí)添加retain/release/autorelease這么簡(jiǎn)單常摧。應(yīng)該是編譯期和運(yùn)行期兩部分共同幫助開(kāi)發(fā)者管理內(nèi)存搅吁。

  • 在編譯期威创,ARC用的是更底層的C接口實(shí)現(xiàn)的retain/release/autorelease,這樣做性能更好谎懦,也是為什么不能在ARC環(huán)境下手動(dòng)retain/release/autorelease肚豺,同時(shí)對(duì)同一上下文的同一對(duì)象的成對(duì)retain/release操作進(jìn)行優(yōu)化(即忽略掉不必要的操作)
  • ARC也包含運(yùn)行期組件,這個(gè)地方做的優(yōu)化比較復(fù)雜界拦,但也不能被忽略吸申,手動(dòng)去做未必優(yōu)化得好,因此直接交給編譯器來(lái)優(yōu)化享甸,相信蘋(píng)果吧截碴!

開(kāi)發(fā)項(xiàng)目時(shí)你是怎么檢查內(nèi)存泄露

  • 靜態(tài)分析 analyze
  • instruments工具里面有個(gè)leak 可以動(dòng)態(tài)分析

如果在block中多次使用 weakSelf的話(huà),可以在block中先使用strongSelf蛉威,防止block執(zhí)行時(shí)weakSelf被意外釋放
對(duì)于非ARC隐岛,將 __weak 改用為 __block 即可

麻煩你設(shè)計(jì)個(gè)簡(jiǎn)單的圖片內(nèi)存緩存器(移除策略是一定要說(shuō)的)

  • 內(nèi)存緩存是個(gè)通用話(huà)題,每個(gè)平臺(tái)都會(huì)涉及到瓷翻。cache算法會(huì)影響到整個(gè)app的表現(xiàn)聚凹。候選人最好能談下自己都了解哪些cache策略及各自的特點(diǎn)。
  • 常見(jiàn)的有FIFO,LRU,LFU等等齐帚。由于NSCache的緩存策略不透明妒牙,一些app開(kāi)發(fā)者會(huì)選擇自己做一套cache機(jī)制,其實(shí)并不難对妄。
  • FIFO : 新訪(fǎng)問(wèn)的數(shù)據(jù)插入FIFO隊(duì)列尾部湘今,數(shù)據(jù)在FIFO隊(duì)列中順序移動(dòng);淘汰FIFO隊(duì)列頭部的數(shù)據(jù)剪菱;
  • LRU : 新數(shù)據(jù)插入到鏈表頭部摩瞎;每當(dāng)緩存數(shù)據(jù)命中,則將數(shù)據(jù)移到鏈表頭部孝常;當(dāng)鏈表滿(mǎn)的時(shí)候旗们,將鏈表尾部的數(shù)據(jù)丟棄;
  • LFU : 新加入數(shù)據(jù)插入到隊(duì)列尾部(因?yàn)橐糜?jì)數(shù)為1)构灸;隊(duì)列中的數(shù)據(jù)被訪(fǎng)問(wèn)后上渴,引用計(jì)數(shù)增加,隊(duì)列重新排序喜颁;當(dāng)需要淘汰數(shù)據(jù)時(shí)稠氮,將已經(jīng)排序的列表最后的數(shù)據(jù)塊刪除;

常見(jiàn)的出現(xiàn)內(nèi)存循環(huán)引用的場(chǎng)景有哪些半开?

  • 定時(shí)器(NSTimer):NSTimer經(jīng)常會(huì)被作為某個(gè)類(lèi)的成員變量隔披,而NSTimer初始化時(shí)要指定self為target,容易造成循環(huán)引用(self->timer->self)寂拆。 另外奢米,若timer一直處于validate的狀態(tài)芥炭,則其引用計(jì)數(shù)將始終大于0,因此在不再使用定時(shí)器以后恃慧,應(yīng)該先調(diào)用invalidate方法
  • block的使用:block在copy時(shí)都會(huì)對(duì)block內(nèi)部用到的對(duì)象進(jìn)行強(qiáng)引用(ARC)或者retainCount增1(非ARC)园蝠。在ARC與非ARC環(huán)境下對(duì)block使用不當(dāng)都會(huì)引起循環(huán)引用問(wèn)題, 一般表現(xiàn)為痢士,某個(gè)類(lèi)將block作為自己的屬性變量彪薛,然后該類(lèi)在block的方法體里面又使用了該類(lèi)本身,簡(jiǎn)單說(shuō)就是self.someBlock =Type var{[self dosomething];或者self.otherVar = XXX;或者_(dá)otherVar = …};出現(xiàn)循環(huán)的原因是:self->block->self或者self->block->_ivar(成員變量)
  • 代理(delegate):在委托問(wèn)題上出現(xiàn)循環(huán)引用問(wèn)題已經(jīng)是老生常談了怠蹂,規(guī)避該問(wèn)題的殺手锏也是簡(jiǎn)單到哭善延,一字訣:聲明delegate時(shí)請(qǐng)用assign(MRC)或者weak(ARC),千萬(wàn)別手賤玩一下retain或者strong城侧,畢竟這基本逃不掉循環(huán)引用了易遣!

對(duì)象添加到通知中心中,當(dāng)通知中心發(fā)通知時(shí)嫌佑,這個(gè)對(duì)象卻已經(jīng)被釋放了豆茫,可能會(huì)出現(xiàn)什么問(wèn)題?

  • 其實(shí)這種只是考查對(duì)通知的簡(jiǎn)單應(yīng)用屋摇。通知是多對(duì)多的關(guān)系揩魂,主要使用場(chǎng)景是跨模塊傳值。當(dāng)某對(duì)象加入到通知中心后炮温,若在對(duì)象被銷(xiāo)毀前不將該對(duì)象從通知中心中移除火脉,當(dāng)發(fā)送通知時(shí),就會(huì)造成崩潰柒啤。這是很常見(jiàn)的倦挂。所以,在添加到通知中心后担巩,一定要在釋放前移除方援。

ARC下不顯式指定任何屬性關(guān)鍵字時(shí),默認(rèn)的關(guān)鍵字都有哪些兵睛?

  • 對(duì)于基本數(shù)據(jù)類(lèi)型默認(rèn)關(guān)鍵字是:atomic,readwrite,assign
  • 對(duì)于普通的Objective-C對(duì)象:atomic,readwrite,strong

寫(xiě)一個(gè)便利構(gòu)造器

+(id)Person {
Person *person=[Person alloc]init];
return [person autorelease]; 備注:ARC時(shí)不用 autorelease
}

寫(xiě)出下面程序段的輸出結(jié)果

NSDictionary *dict = [NSDictionary dictionaryWithObject:@"a string value" forKey:@"akey"]; NSLog(@"%@", [dict objectForKey:@"akey"]);
[dict release];
打印輸出 a string value,然后崩潰----原因:便利構(gòu)造器創(chuàng)建的對(duì)象,之后的release,會(huì)造成過(guò)度釋放

請(qǐng)寫(xiě)出以下代碼的執(zhí)行結(jié)果

NSString * name = [ [ NSString alloc] init ];
name = @”Habb”;
[ name release];
打印輸出結(jié)果是: Habb,在[name release]前后打印均有輸出結(jié)果 ---會(huì)造成內(nèi)存泄露---原先指向的區(qū)域變成了野指針,之后的釋放,不能釋放之前創(chuàng)建的區(qū)域

寫(xiě)出方法獲取ios內(nèi)存使用情況肯骇?

iOS是如何管理內(nèi)存的?

我相信很多人的回答是內(nèi)存管理的黃金法則祖很,其實(shí)如果我是面試官,我想要的答案不是這樣的漾脂。我希望的回答是工作中如何處理內(nèi)存管理的假颇。
參考答案:

  • Block內(nèi)存管理:由于使用block很容易造成循環(huán)引用,因此一定要小心內(nèi)存管理問(wèn)題骨稿。最好在基類(lèi)controller下重寫(xiě)dealloc笨鸡,加一句打印日志姜钳,表示類(lèi)可以得到釋放。如果出現(xiàn)無(wú)打印信息形耗,說(shuō)明這個(gè)類(lèi)一直得不到釋放哥桥,表明很有可能是使用block的地方出現(xiàn)循環(huán)引用了。對(duì)于block中需要引用外部controller的屬性或者成員變量時(shí)激涤,一定要使用弱引用拟糕,特別是成員變量像_testId這樣的,很多人都沒(méi)有使用弱引用倦踢,導(dǎo)致內(nèi)存得不到釋放送滞。
  • 對(duì)于普通所創(chuàng)建的對(duì)象,因?yàn)楝F(xiàn)在都是ARC項(xiàng)目辱挥,所以記住內(nèi)存管理的黃金法則就可以解決犁嗅。

很多內(nèi)置的類(lèi),如tableview的delegate的屬性是assign不是retain晤碘?

  • tableview的代理一般都是它所屬的控制器褂微,控制器會(huì)對(duì)它內(nèi)部的view進(jìn)行一次retain操作,而tableview對(duì)代理控制器也進(jìn)行一次retain操作园爷,就會(huì)出現(xiàn)循環(huán)引用問(wèn)題蕊梧。

文章如有問(wèn)題,請(qǐng)留言腮介,我將及時(shí)更正肥矢。

滿(mǎn)地打滾賣(mài)萌求贊,如果本文幫助到你叠洗,輕點(diǎn)下方的紅心甘改,給作者君增加更新的動(dòng)力。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灭抑,一起剝皮案震驚了整個(gè)濱河市十艾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌腾节,老刑警劉巖忘嫉,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異案腺,居然都是意外死亡庆冕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)劈榨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)访递,“玉大人,你說(shuō)我怎么就攤上這事同辣】阶耍” “怎么了惭载?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)响巢。 經(jīng)常有香客問(wèn)我描滔,道長(zhǎng),這世上最難降的妖魔是什么踪古? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任含长,我火速辦了婚禮,結(jié)果婚禮上灾炭,老公的妹妹穿的比我還像新娘茎芋。我一直安慰自己,他們只是感情好蜈出,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布田弥。 她就那樣靜靜地躺著,像睡著了一般铡原。 火紅的嫁衣襯著肌膚如雪偷厦。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天燕刻,我揣著相機(jī)與錄音只泼,去河邊找鬼。 笑死卵洗,一個(gè)胖子當(dāng)著我的面吹牛请唱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播过蹂,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼十绑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了酷勺?” 一聲冷哼從身側(cè)響起本橙,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎脆诉,沒(méi)想到半個(gè)月后甚亭,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡击胜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年渤滞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了仿滔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拗盒。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缀台,死狀恐怖缭付,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情兆览,我是刑警寧澤苔埋,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站亡呵,受9級(jí)特大地震影響抽活,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锰什,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一下硕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧汁胆,春花似錦梭姓、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至铸题,卻和暖如春铡恕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背丢间。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工探熔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烘挫。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓诀艰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親饮六。 傳聞我的和親對(duì)象是個(gè)殘疾皇子其垄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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

  • iOS內(nèi)存管理 概述 什么是內(nèi)存管理 應(yīng)用程序內(nèi)存管理是在程序運(yùn)行時(shí)分配內(nèi)存(比如創(chuàng)建一個(gè)對(duì)象,會(huì)增加內(nèi)存占用)與...
    蚊香醬閱讀 5,723評(píng)論 8 119
  • 內(nèi)存管理 簡(jiǎn)述OC中內(nèi)存管理機(jī)制。與retain配對(duì)使用的方法是dealloc還是release喜滨,為什么捉捅?需要與a...
    丶逐漸閱讀 1,964評(píng)論 1 16
  • 29.理解引用計(jì)數(shù) Objective-C語(yǔ)言使用引用計(jì)數(shù)來(lái)管理內(nèi)存,也就是說(shuō)虽风,每個(gè)對(duì)象都有個(gè)可以遞增或遞減的計(jì)數(shù)...
    Code_Ninja閱讀 1,490評(píng)論 1 3
  • 內(nèi)存管理是程序在運(yùn)行時(shí)分配內(nèi)存棒口、使用內(nèi)存,并在程序完成時(shí)釋放內(nèi)存的過(guò)程辜膝。在Objective-C中无牵,也被看作是在眾...
    蹲瓜閱讀 3,079評(píng)論 1 8
  • 01 逛街時(shí)茎毁,看到大排長(zhǎng)龍的餐廳,總能讓吃貨們?yōu)橹v足,到處嘗鮮是吃貨的興趣七蜘,然而親自做美食谭溉,是吃貨對(duì)美食熱愛(ài)的一...
    冰島之鯨閱讀 476評(píng)論 0 2