內(nèi)存管理
ARC處理原理
ARC是Objective-C編譯器的特性,而不是運(yùn)行時(shí)特性或者垃圾回收機(jī)制,ARC所做的只不過是在代碼編譯時(shí)為你自動(dòng)在合適的位置插入release或autorelease开瞭,只要沒有強(qiáng)指針指向?qū)ο蠹嵛撸瑢?duì)象就會(huì)被釋放凶掰。
前端編譯器
前端編譯器會(huì)為“擁有的”每一個(gè)對(duì)象插入相應(yīng)的release語句吴汪。如果對(duì)象的所有權(quán)修飾符是__strong,那么它就是被擁有的喇闸。如果在某個(gè)方法內(nèi)創(chuàng)建了一個(gè)對(duì)象袄琳,前端編譯器會(huì)在方法末尾自動(dòng)插入release語句以銷毀它。而類擁有的對(duì)象(實(shí)例變量/屬性)會(huì)在dealloc方法內(nèi)被釋放燃乍。事實(shí)上唆樊,你并不需要寫dealloc方法或調(diào)用父類的dealloc方法,ARC會(huì)自動(dòng)幫你完成一切刻蟹。此外逗旁,由編譯器生成的代碼甚至?xí)饶阕约簩懙膔elease語句的性能還要好,因?yàn)榫庉嬈骺梢宰鞒鲆恍┘僭O(shè)舆瘪。在ARC中片效,沒有類可以覆蓋release方法,也沒有調(diào)用它的必要介陶。ARC會(huì)通過直接使用objc_release來優(yōu)化調(diào)用過程堤舒。而對(duì)于retain也是同樣的方法色建。ARC會(huì)調(diào)用objc_retain來取代保留消息哺呜。
ARC優(yōu)化器
雖然前端編譯器聽起來很厲害的樣子,但代碼中有時(shí)仍會(huì)出現(xiàn)幾個(gè)對(duì)retain和release的重復(fù)調(diào)用箕戳。ARC優(yōu)化器負(fù)責(zé)移除多余的retain和release語句某残,確保生成的代碼運(yùn)行速度高于手動(dòng)引用計(jì)數(shù)的代碼。
下面關(guān)于Objective-C內(nèi)存管理的描述錯(cuò)誤的是
A 當(dāng)使用ARC來管理內(nèi)存時(shí)陵吸,代碼中不可以出現(xiàn)autorelease
B autoreleasepool 在 drain 的時(shí)候會(huì)釋放在其中分配的對(duì)象
C 當(dāng)使用ARC來管理內(nèi)存時(shí)玻墅,在線程中大量分配對(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)存饶唤。如果在線程中需要大量分配內(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)用父類的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í)候,往往要通過讓其中一端使用 weak 來解決,比如: delegate 代理屬性
自身已經(jīng)對(duì)它進(jìn)行一次強(qiáng)引用,沒有必要再強(qiáng)引用一次,此時(shí)也會(huì)使用 weak,自定義 IBOutlet 控件屬性一般也使用 weak刻蚯;當(dāng)然,也可以使用strong桑嘶。
weak與assign的不同?
weak 此特質(zhì)表明該屬性定義了一種“非擁有關(guān)系” (nonowning relationship)炊汹。為這種屬性設(shè)置新值時(shí),設(shè)置方法既不保留新值逃顶,也不釋放舊值讨便。此特質(zhì)同assign類似, 然而在屬性所指的對(duì)象遭到摧毀時(shí)以政,屬性值也會(huì)清空(nil out)霸褒。 而 assign 的“設(shè)置方法”只會(huì)執(zhí)行針對(duì)“純量類型” (scalar type,例如 CGFloat 或 NSlnteger 等)的簡單賦值操作盈蛮。
assigin 可以用非 OC 對(duì)象,而 weak 必須用于 OC 對(duì)象
調(diào)用對(duì)象的release 方法會(huì)銷毀對(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)釋放池常見面試代碼
for (int i = 0; i < someLargeNumber; ++i)
{
NSString *string = @"Abc";
string = [string lowercaseString];
string = [string stringByAppendingString:@"xyz"];
NSLog(@"%@",string);
}
問:以上代碼存在什么樣的問題?如果循環(huán)的次數(shù)非常大時(shí)袒炉,應(yīng)該如何修改旁理?
存在問題:問題處在每執(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)存空間將被耗盡而沒有被釋放掉,所以就出現(xiàn)了內(nèi)存溢出的現(xiàn)象劲适。
解決辦法1:如果i比較大楷掉,可以用@autoreleasepool {}解決,放在for循環(huán)外,循環(huán)結(jié)束后烹植,銷毀創(chuàng)建的對(duì)象斑鸦,解決占據(jù)棧區(qū)內(nèi)存的問題
解決方法2:如果i玩命大,一次循環(huán)都會(huì)造成自動(dòng)釋放池被填滿草雕,自動(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中沒有多繼承墩虹,因此其內(nèi)存布局還是很簡單的嘱巾,就是:最前面有個(gè)isa指針,然后父類的實(shí)例變量存放在子類的成員變量之前
看下面的程序,第一個(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)存池?
用戶自己創(chuàng)建的數(shù)據(jù)線程,則需要?jiǎng)?chuàng)建該線程的內(nèi)存池
如果我們不創(chuàng)建內(nèi)存池惧所,是否有內(nèi)存池提供給我們?
界面線程維護(hù)著自己的內(nèi)存池骤坐,用戶自己創(chuàng)建的數(shù)據(jù)線程,則需要?jiǎng)?chuàng)建該線程的內(nèi)存池
蘋果是如何實(shí)現(xiàn)autoreleasepool的下愈?
autoreleasepool以一個(gè)隊(duì)列數(shù)組的形式實(shí)現(xiàn),主要通過下列三個(gè)函數(shù)完成.
? objc_autoreleasepoolPush
? objc_autoreleasepoolPop
? objc_autorelease
看函數(shù)名就可以知道纽绍,對(duì)autorelease分別執(zhí)行push、pop操作势似。銷毀對(duì)象時(shí)執(zhí)行release操作拌夏。
objc使用什么機(jī)制管理對(duì)象內(nèi)存?
通過引用計(jì)數(shù)器(retainCount)的機(jī)制來決定對(duì)象是否需要釋放叫编。 每次runloop完成一個(gè)循環(huán)的時(shí)候辖佣,都會(huì)檢查對(duì)象的 retainCount霹抛,如果retainCount為0搓逾,說明該對(duì)象沒有地方需要繼續(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ì)閃退, 影響用戶體驗(yàn). 為了保證程序的運(yùn)行流暢, 必須進(jìn)行內(nèi)存管理
內(nèi)存管理的范圍?
管理所有繼承自NSObject的對(duì)象, 對(duì)基本數(shù)據(jù)類型無效.是因?yàn)閷?duì)象和其他數(shù)據(jù)類型在系統(tǒng)中存儲(chǔ)的空間不一樣,其他局部變量主要存儲(chǔ)在棧區(qū)(因?yàn)榛緮?shù)據(jù)類型占用的存儲(chǔ)空間是固定的,一般存放于棧區(qū)),而對(duì)象存儲(chǔ)于堆中,當(dāng)代碼塊結(jié)束時(shí),這個(gè)代碼塊所涉及到的所有局部變量會(huì)自動(dòng)彈棧清空,指向?qū)ο蟮闹羔樢矔?huì)被回收,這時(shí)對(duì)象就沒有指針指向,但依然存在于堆內(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作為LLVM3.0編譯器的一項(xiàng)特性, 在iOS5.0 (Xcode4) 版本后推出的朗兵。
ARC的判斷準(zhǔn)則, 只要沒有強(qiáng)指針指向?qū)ο? 對(duì)象就會(huì)被釋放.
iOS是如何管理內(nèi)存的?
這個(gè)問題的話上一個(gè)問題也提到過,講下block的內(nèi)存管理,ARC下的黃金法則就行顶滩。
這里說下swift里的內(nèi)存管理:
delgate照樣weak修飾,閉包前面用[weak self],swift里的新東西,unowned,舉例,如果self在閉包被調(diào)用的時(shí)候可能為空,則用weak,反之亦然,如果為空時(shí)使用了unowned,程序會(huì)崩潰,類似訪問了懸掛指針,在oc中類似于unsafe_unretained,類似assign修飾了oc對(duì)象,對(duì)象被銷毀后,被unowned修飾的對(duì)象不會(huì)為空,但是unowned訪問速度更快,因?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
誰創(chuàng)建, 就由誰來release
如果你通過alloc, new, copy 來創(chuàng)建一個(gè)對(duì)象, 當(dāng)你不想用這個(gè)對(duì)象的時(shí)候就必須調(diào)用release 或者autorelease 讓引用計(jì)數(shù)器減1
不是你創(chuàng)建的就不用你負(fù)責(zé) release
誰retain 誰release
只要你調(diào)用了retain ,無論這個(gè)對(duì)象如何生成, 都需要調(diào)用release
總結(jié):
有加就應(yīng)該有減, 曾讓某個(gè)計(jì)數(shù)器加1, 就應(yīng)該讓其在最后減1
內(nèi)存管理研究的對(duì)象:
野指針:指針變量沒有進(jìn)行初始化或指向的空間已經(jīng)被釋放余掖。
使用野指針調(diào)用對(duì)象方法,會(huì)報(bào)異常礁鲁,程序崩潰盐欺。
通常再調(diào)用完release方法后赁豆,把保存對(duì)象指針的地址清空,賦值為nil冗美,找oc中沒有空指針異常魔种,所以[nil retain]調(diào)用方法不會(huì)有異常。
內(nèi)存泄露
如 Person * person = [Person new]; (對(duì)象提前賦值nil或者清空)在棧區(qū)的person已經(jīng)被釋放, 而堆區(qū)new產(chǎn)生的對(duì)象還沒有釋放, 就會(huì)造成內(nèi)存泄露
在MRC手動(dòng)引用計(jì)數(shù)器模式下, 造成內(nèi)存泄露的情況
沒有配對(duì)釋放粉洼,不符合內(nèi)存管理原則
對(duì)象提前賦值nil或者清空节预,導(dǎo)致release不起作用。
僵尸對(duì)象 : 堆中已經(jīng)被釋放的對(duì)象(retainCount = 0)
空指針 : 指針賦值為空,nil
如何判斷對(duì)象已經(jīng)被銷毀
重寫dealloc方法属韧,對(duì)象銷毀時(shí)安拟,會(huì)調(diào)用,重寫時(shí)一定要[super dealloc]
retainCount = 0宵喂,使用retain能否復(fù)活對(duì)象
已經(jīng)被釋放的對(duì)象無法復(fù)活
對(duì)象與對(duì)象之間存在的關(guān)系
繼承關(guān)系
組合關(guān)系(是一種強(qiáng)烈的包含關(guān)系)
依賴關(guān)系(對(duì)象作為方法參數(shù)傳遞)
對(duì)象的組合關(guān)系中去扣,確保成員變量不被提前釋放?
重寫set方法樊破,在set方法中愉棱,retain該對(duì)象。
成員變量的對(duì)象哲戚,在哪里配對(duì)釋放奔滑?
dealloc中釋放
對(duì)象組合關(guān)系中,內(nèi)存泄露有哪幾種情況顺少?
set方法沒有retain對(duì)象
沒有release舊對(duì)象
沒有判斷向set方法中傳入的是否為同一個(gè)對(duì)象
正確重寫set方法
判斷是否為同一對(duì)象
release舊對(duì)象
retain新對(duì)象
分別描述內(nèi)存管理要點(diǎn)朋其、autorelease、release脆炎、NSAutoreleasePool?并說明autorelease是什么時(shí)候被release的?簡述什么時(shí)候由你負(fù)責(zé)釋放對(duì)象,什么時(shí)候不由你釋放?[NSAutoreleasePool release]和[NSAutoreleasePool drain]有什么區(qū)別?
內(nèi)存管理要點(diǎn):Objective-C 使用引用計(jì)數(shù)機(jī)制(retainCount)來管理內(nèi)存梅猿。
內(nèi)存每被引用一次,該內(nèi)存的引用計(jì)數(shù)+1,每被釋放一次引 用計(jì)數(shù)-1。
當(dāng)引用計(jì)數(shù) = 0 的時(shí)候,調(diào)用該對(duì)象的 dealloc 方法,來徹底從內(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ù)類型是否有mutable袱蚓,如有為深拷貝,新對(duì)象計(jì)數(shù)為1几蜻,如果沒有喇潘,為淺拷貝,計(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是通過接收對(duì)象向它發(fā)送的autorelease消息,記錄該對(duì)象的release消息,當(dāng)自動(dòng)釋放池被銷毀時(shí),會(huì)自動(dòng)向池中的對(duì)象發(fā)送release消息颖低。
autorelease 是在自動(dòng)釋放池被銷毀,向池中的對(duì)象發(fā)送release
只能釋放自己擁有的對(duì)象。
區(qū)別是:在引用計(jì)數(shù)環(huán)境下(在不使用ARC情況下),兩者基本一樣,在GC(垃圾回收制)環(huán)境下,release 是一個(gè)no-op(無效操作),所以無論是不是GC都使用drain
面試中內(nèi)存管理,release和autorelease的含義?這里尤其要強(qiáng)調(diào)下autorelease,它引申出自動(dòng)釋放池,也能引申出Run loop!
自動(dòng)釋放池是什么,如何工作 ?
什么是自動(dòng)釋放池:用來存儲(chǔ)多個(gè)對(duì)象類型的指針變量
自動(dòng)釋放池對(duì)池內(nèi)對(duì)象的作用:存入池內(nèi)的對(duì)象弧烤,當(dāng)自動(dòng)釋放池被銷毀時(shí)忱屑,會(huì)對(duì)池內(nèi)對(duì)象全部做一次release操作
對(duì)象如何加入池中:調(diào)用對(duì)象的autorelease方法
自動(dòng)釋放池能嵌套使用嗎:能
自動(dòng)釋放池何時(shí)被銷毀 :簡單的看,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)釋放池銷毀時(shí)銷毀對(duì)象脏毯,延遲release銷毀時(shí)間
自動(dòng)釋放池什么時(shí)候釋放闹究?
通過Observer監(jiān)聽RunLoop的狀態(tài),一旦監(jiān)聽到RunLoop即將進(jìn)入睡眠等待狀態(tài)食店,就釋放自動(dòng)釋放池(kCFRunLoopBeforeWaiting)
IPhone OS有沒有垃圾回收?autorelease 和垃圾回收制(gc)有什么關(guān)系?
iOS 中沒有垃圾回收渣淤。autorelease只是延遲釋放,gc是每隔一段時(shí)間詢問程序,看是否有無指針指向的對(duì)象,若有,就將它回收。他們兩者沒有什么關(guān)系吉嫩。
ARC問題
什么是arc機(jī)制:自動(dòng)引用計(jì)數(shù).
系統(tǒng)判斷對(duì)象是否銷毀的依據(jù):指向?qū)ο蟮膹?qiáng)指針是否被銷毀
arc的本質(zhì):對(duì)retainCount計(jì)算价认,創(chuàng)建+1 清空指針 - 1 或者到達(dá)autoreleasepool的大括號(hào)-1
arc目的:不需要程序員關(guān)心retain和release操作.
如何解決arc機(jī)制下類的相互引用:.h文件中使用@class關(guān)鍵字聲明一個(gè)類,兩端不能都用強(qiáng)指針自娩,一端用strong一端用weak
ARC通過什么方式幫助開發(fā)者管理內(nèi)存用踩?
ARC相對(duì)于MRC,不是在編譯時(shí)添加retain/release/autorelease這么簡單忙迁。應(yīng)該是編譯期和運(yùn)行期兩部分共同幫助開發(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)化得好嵌言,因此直接交給編譯器來優(yōu)化嗅回,相信蘋果吧!
開發(fā)項(xiàng)目時(shí)你是怎么檢查內(nèi)存泄露
靜態(tài)分析 analyze
instruments工具里面有個(gè)leak 可以動(dòng)態(tài)分析
如果在block中多次使用 weakSelf的話摧茴,可以在block中先使用strongSelf绵载,防止block執(zhí)行時(shí)weakSelf被意外釋放
對(duì)于非ARC,將 __weak 改用為 __block 即可
麻煩你設(shè)計(jì)個(gè)簡單的圖片內(nèi)存緩存器(移除策略是一定要說的)
內(nèi)存緩存是個(gè)通用話題蓬蝶,每個(gè)平臺(tái)都會(huì)涉及到尘分。cache算法會(huì)影響到整個(gè)app的表現(xiàn)。候選人最好能談下自己都了解哪些cache策略及各自的特點(diǎn)丸氛。
常見的有FIFO,LRU,LFU等等。由于NSCache的緩存策略不透明著摔,一些app開發(fā)者會(huì)選擇自己做一套cache機(jī)制缓窜,其實(shí)并不難。
FIFO : 新訪問的數(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)鏈表滿的時(shí)候,將鏈表尾部的數(shù)據(jù)丟棄黄娘;
LFU : 新加入數(shù)據(jù)插入到隊(duì)列尾部(因?yàn)橐糜?jì)數(shù)為1)峭状;隊(duì)列中的數(shù)據(jù)被訪問后,引用計(jì)數(shù)增加逼争,隊(duì)列重新排序优床;當(dāng)需要淘汰數(shù)據(jù)時(shí),將已經(jīng)排序的列表最后的數(shù)據(jù)塊刪除誓焦;
常見的出現(xiàn)內(nèi)存循環(huán)引用的場景有哪些胆敞?
定時(shí)器(NSTimer):NSTimer經(jīng)常會(huì)被作為某個(gè)類的成員變量,而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)引用問題匪燕, 一般表現(xiàn)為,某個(gè)類將block作為自己的屬性變量喧笔,然后該類在block的方法體里面又使用了該類本身帽驯,簡單說就是self.someBlock =Type var{[self dosomething];或者self.otherVar = XXX;或者_(dá)otherVar = …};出現(xiàn)循環(huán)的原因是:self->block->self或者self->block->_ivar(成員變量)
代理(delegate):在委托問題上出現(xiàn)循環(huán)引用問題已經(jīng)是老生常談了,規(guī)避該問題的殺手锏也是簡單到哭书闸,一字訣:聲明delegate時(shí)請用assign(MRC)或者weak(ARC)尼变,千萬別手賤玩一下retain或者strong,畢竟這基本逃不掉循環(huán)引用了浆劲!
對(duì)象添加到通知中心中嫌术,當(dāng)通知中心發(fā)通知時(shí),這個(gè)對(duì)象卻已經(jīng)被釋放了牌借,可能會(huì)出現(xiàn)什么問題度气?
其實(shí)這種只是考查對(duì)通知的簡單應(yīng)用。通知是多對(duì)多的關(guān)系膨报,主要使用場景是跨模塊傳值磷籍。當(dāng)某對(duì)象加入到通知中心后适荣,若在對(duì)象被銷毀前不將該對(duì)象從通知中心中移除,當(dāng)發(fā)送通知時(shí)院领,就會(huì)造成崩潰弛矛。這是很常見的。所以比然,在添加到通知中心后丈氓,一定要在釋放前移除。
ARC下不顯式指定任何屬性關(guān)鍵字時(shí)强法,默認(rèn)的關(guān)鍵字都有哪些万俗?
對(duì)于基本數(shù)據(jù)類型默認(rèn)關(guān)鍵字是:atomic,readwrite,assign
對(duì)于普通的Objective-C對(duì)象:atomic,readwrite,strong
寫一個(gè)便利構(gòu)造器
+(id)Person {
Person *person=[Person alloc]init];
return [person autorelease]; 備注:ARC時(shí)不用 autorelease
}
寫出下面程序段的輸出結(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ì)造成過度釋放
請寫出以下代碼的執(zhí)行結(jié)果
NSString * name = [ [ NSString alloc] init ];
name = @”Habb”;
[ name release];
打印輸出結(jié)果是: Habb,在[name release]前后打印均有輸出結(jié)果 ---會(huì)造成內(nèi)存泄露---原先指向的區(qū)域變成了野指針,之后的釋放,不能釋放之前創(chuàng)建的區(qū)域
寫出方法獲取ios內(nèi)存使用情況?
iOS是如何管理內(nèi)存的拟烫?
我相信很多人的回答是內(nèi)存管理的黃金法則该编,其實(shí)如果我是面試官,我想要的答案不是這樣的硕淑。我希望的回答是工作中如何處理內(nèi)存管理的课竣。
參考答案:
Block內(nèi)存管理:由于使用block很容易造成循環(huán)引用,因此一定要小心內(nèi)存管理問題置媳。最好在基類controller下重寫dealloc于樟,加一句打印日志,表示類可以得到釋放拇囊。如果出現(xiàn)無打印信息迂曲,說明這個(gè)類一直得不到釋放,表明很有可能是使用block的地方出現(xiàn)循環(huán)引用了寥袭。對(duì)于block中需要引用外部controller的屬性或者成員變量時(shí)路捧,一定要使用弱引用,特別是成員變量像_testId這樣的传黄,很多人都沒有使用弱引用杰扫,導(dǎo)致內(nèi)存得不到釋放。
對(duì)于普通所創(chuàng)建的對(duì)象膘掰,因?yàn)楝F(xiàn)在都是ARC項(xiàng)目章姓,所以記住內(nèi)存管理的黃金法則就可以解決。
很多內(nèi)置的類识埋,如tableview的delegate的屬性是assign不是retain凡伊?
tableview的代理一般都是它所屬的控制器,控制器會(huì)對(duì)它內(nèi)部的view進(jìn)行一次retain操作窒舟,而tableview對(duì)代理控制器也進(jìn)行一次retain操作系忙,就會(huì)出現(xiàn)循環(huán)引用問題。
.主要是你在iOS里使用 while (true) {} 無線循環(huán)時(shí)辜纲, iOS ARC默認(rèn)認(rèn)為你這個(gè)方法永遠(yuǎn)沒有執(zhí)行完笨觅,所以不會(huì)去主動(dòng)釋放你方法里的對(duì)象拦耐,這一點(diǎn)和JAVA不一樣耕腾, 所以很多JAVA開發(fā)者轉(zhuǎn)iOS后習(xí)慣性的使用while(true){} 導(dǎo)致項(xiàng)目里存在這種內(nèi)存隱患见剩,導(dǎo)致內(nèi)存無限增加
----01>添加@autorelesepool{
}
----02>使用nstime做無限循環(huán),arc下會(huì)自動(dòng)釋放內(nèi)存
2.ARC模式下oc對(duì)象與非oc對(duì)象之間的橋接 非oc對(duì)象需要手動(dòng)釋放扫俺。
__bridge:不涉及對(duì)象所有關(guān)系改變
__bridge_transfer:給予 ARC 所有權(quán)
__bridge_retained:解除 ARC 所有權(quán)
3.如果在WebView載入完成之前關(guān)閉畫面的話苍苞,畫面關(guān)閉后,ViewController也釋放了狼纬。但由于WebView正在載入頁面羹呵,而不會(huì)馬上被釋放,等到頁面載入完畢后疗琉,回調(diào)delegate(ViewController)中的方法冈欢,由于此時(shí)ViewController已經(jīng)被釋放,所以會(huì)出錯(cuò)盈简。(message sent to deallocated instance)
解決辦法是在dealloc中把WebView的delegate釋放凑耻。
4.ARC模式下,自動(dòng)回收只針對(duì)Objective-C對(duì)象有效柠贤,對(duì)于使用create,copy,retain等生成的Core Foundation對(duì)象還是需要我們手動(dòng)進(jìn)行釋放的香浩,CFRelease()