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

為什么管理內(nèi)存:

程序在運(yùn)行的時(shí)候择卦,要?jiǎng)?chuàng)建大量的對(duì)象蝇庭,這些對(duì)象放在堆和棧上醉鳖。(基本類(lèi)型放在棧上,由系統(tǒng)自動(dòng)管理哮内。) 而放在堆上的對(duì)象如果得不到及時(shí)釋放盗棵,就會(huì)占用大量?jī)?nèi)存。OC中沒(méi)有垃圾回收機(jī)制北发,所以我們要手動(dòng)管理內(nèi)存(ARC之前)
任何繼承了NSObject的對(duì)象需要進(jìn)行內(nèi)存管理

原理:

依賴(lài)對(duì)象引用計(jì)數(shù)器+1 -1:在ObjC中對(duì)象創(chuàng)建后內(nèi)部都有一個(gè)與之對(duì)應(yīng)的整數(shù)(retainCount)纹因,叫“引用計(jì)數(shù)器”,當(dāng)一個(gè)對(duì)象在創(chuàng)建之后它的引用計(jì)數(shù)器為1琳拨,當(dāng)調(diào)用這個(gè)對(duì)象的alloc瞭恰、retain、new狱庇、copy方法之后引用計(jì)數(shù)器自動(dòng)在原來(lái)的基礎(chǔ)上加1(ObjC中調(diào)用一個(gè)對(duì)象的方法就是給這個(gè)對(duì)象發(fā)送一個(gè)消息)惊畏,當(dāng)調(diào)用這個(gè)對(duì)象的release方法之后它的引用計(jì)數(shù)器減1,如果一個(gè)對(duì)象的引用計(jì)數(shù)器為0密任,則系統(tǒng)會(huì)自動(dòng)調(diào)用這個(gè)對(duì)象的dealloc方法來(lái)銷(xiāo)毀這個(gè)對(duì)象颜启。

內(nèi)存管理機(jī)制:
程序運(yùn)行過(guò)程中要在堆和棧中創(chuàng)建大量的對(duì)象,int bool等基本類(lèi)型放在棧上浪讳,由系統(tǒng)自己管理缰盏。存儲(chǔ)在堆中的對(duì)象,系統(tǒng)并不會(huì)自動(dòng)釋放堆中的內(nèi)存淹遵。如果一個(gè)對(duì)象創(chuàng)建并使用后沒(méi)有得到及時(shí)釋放那么就會(huì)占用大量?jī)?nèi)存乳规。
內(nèi)存的管理是依賴(lài)對(duì)象引用計(jì)數(shù)器來(lái)進(jìn)行的:在ObjC中每個(gè)對(duì)象內(nèi)部都有一個(gè)與之對(duì)應(yīng)的整數(shù)(retainCount),叫“引用計(jì)數(shù)器”合呐,當(dāng)一個(gè)對(duì)象在創(chuàng)建之后它的引用計(jì)數(shù)器為1暮的,當(dāng)調(diào)用這個(gè)對(duì)象的alloc、retain淌实、new冻辩、copy方法之后引用計(jì)數(shù)器自動(dòng)在原來(lái)的基礎(chǔ)上加1(ObjC中調(diào)用一個(gè)對(duì)象的方法就是給這個(gè)對(duì)象發(fā)送一個(gè)消息)猖腕,當(dāng)調(diào)用這個(gè)對(duì)象的release方法之后它的引用計(jì)數(shù)器減1,如果一個(gè)對(duì)象的引用計(jì)數(shù)器為0恨闪,則系統(tǒng)會(huì)自動(dòng)調(diào)用這個(gè)對(duì)象的dealloc方法來(lái)銷(xiāo)毀這個(gè)對(duì)象倘感。
對(duì)于int,bool等基本類(lèi)型,這些直接在棧上開(kāi)辟的內(nèi)存咙咽,由系統(tǒng)自己管理老玛,用assign;
對(duì)于在堆中開(kāi)辟的內(nèi)存钧敞,我們需要維護(hù)內(nèi)存的計(jì)數(shù)器蜡豹,首次創(chuàng)建內(nèi)存后,內(nèi)存計(jì)數(shù)器+1溉苛,當(dāng)指針A付給指針B的時(shí)候镜廉,給內(nèi)存計(jì)數(shù)器再+1,告訴其他指針愚战,我B也引用了這塊內(nèi)存娇唯,這個(gè)時(shí)候,retain正是做這個(gè)工作的寂玲,只是oc封裝了這個(gè)過(guò)程塔插。其實(shí)copy更好理解,如果指針A和指針B不想相互牽扯拓哟,A管理A的內(nèi)存佑淀,B管理B的內(nèi)存,copy正是為這個(gè)而生彰檬。
在+和-之間保持平衡伸刃,不是所有的成員變量都要設(shè)置屬性。釋放帶屬性的成員變量的時(shí)候逢倍,手動(dòng)設(shè)置為nil,用self.屬性=nil较雕。否則可能造成野指針錯(cuò)誤碉哑,而且需要注意在ObjC中給空對(duì)象發(fā)送消息是不會(huì)引起錯(cuò)誤的亮蒋。

原則:

誰(shuí)創(chuàng)建,誰(shuí)釋放慎玖,誰(shuí)引用贮尖,誰(shuí)管理趁怔。

動(dòng)態(tài)內(nèi)存管理的黃金法則薪前,如果我們alloc/new/retain/copy/mutableCopy了一個(gè)對(duì)象,那么我們需要對(duì)這個(gè)對(duì)象進(jìn)行release或autorelease!

自動(dòng)釋放池:

autorelease方法不會(huì)改變對(duì)象的引用計(jì)數(shù)器关斜,只是將這個(gè)對(duì)象放到自動(dòng)釋放池中示括;

自動(dòng)釋放池(@autoreleaespool)實(shí)質(zhì)是當(dāng)自動(dòng)釋放池銷(xiāo)毀后調(diào)用對(duì)象的release方法,不一定就能銷(xiāo)毀對(duì)象(例如如果一個(gè)對(duì)象的引用計(jì)數(shù)器>1則此時(shí)就無(wú)法銷(xiāo)毀)痢畜;

由于自動(dòng)釋放池最后統(tǒng)一銷(xiāo)毀對(duì)象垛膝,因此如果一個(gè)操作比較占用內(nèi)存(對(duì)象比較多或者對(duì)象占用資源比較多),最好不要放到自動(dòng)釋放池或者考慮放到多個(gè)自動(dòng)釋放池丁稀;

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

當(dāng)您向一個(gè)對(duì)象發(fā)送一個(gè)autorelease消息時(shí)吼拥,將該對(duì)象的一個(gè)引用放入到最新的自動(dòng)釋放池。它仍然是個(gè)正當(dāng)?shù)膶?duì)象二驰,因此自動(dòng)釋放池定義的作用域內(nèi)的其它對(duì)象可以向它發(fā)送消息扔罪。當(dāng)程序執(zhí)行到作用域結(jié)束的位置時(shí)秉沼,自動(dòng)釋放池就會(huì)被釋放桶雀,池中的所有對(duì)象也就被釋放。

自動(dòng)釋放池:
如果不是萬(wàn)般無(wú)奈的情況下唬复,我建議不使用autorelease構(gòu)建對(duì)象矗积。但是,在一個(gè)方法中返回一個(gè)對(duì)象的指針敞咧,這個(gè)時(shí)候棘捣,我們不方便管理方法返回的對(duì)象,這種情況休建,用autorelease是比較明智的選擇乍恐。
如果不方便管理,那就要用autorelease了测砂。不要輕易把a(bǔ)utorelease對(duì)象付給retain屬性茵烈,因?yàn)槟愫苡锌赡芡浗o屬性設(shè)置nil。
向一個(gè)對(duì)象發(fā)送一個(gè)autorelease消息時(shí)砌些,autorelease方法不會(huì)改變對(duì)象的引用計(jì)數(shù)器呜投,只是將這個(gè)對(duì)象放到自動(dòng)釋放池中,它仍然是個(gè)正當(dāng)?shù)膶?duì)象存璃,因此自動(dòng)釋放池定義的作用域內(nèi)的其它對(duì)象可以向它發(fā)送消息仑荐。
自動(dòng)釋放池(@autoreleaespool)實(shí)質(zhì)是當(dāng)自動(dòng)釋放池銷(xiāo)毀后調(diào)用對(duì)象的release方法粘招,不一定就能銷(xiāo)毀對(duì)象(例如如果一個(gè)對(duì)象的引用計(jì)數(shù)器>1則此時(shí)就無(wú)法銷(xiāo)毀);
由于自動(dòng)釋放池最后統(tǒng)一銷(xiāo)毀對(duì)象男图,因此如果一個(gè)操作比較占用內(nèi)存(對(duì)象比較多或者對(duì)象占用資源比較多)示姿,最好不要放到自動(dòng)釋放池或者考慮放到多個(gè)自動(dòng)釋放池栈戳;
請(qǐng)說(shuō)出下面代碼是否有問(wèn)題,如果有問(wèn)題請(qǐng)修改
@autoreleasepool {
for (int i=0; i<largeNumber; i++) {
Person *per = [[Person alloc] init];
[per autorelease];
}
}
內(nèi)存管理的原則:如果對(duì)一個(gè)對(duì)象使用了alloc子檀、copy、retain褂痰,那么你必須使用相應(yīng)的release或者autorelease。咋一看缩歪,這道題目有alloc,也有autorelease匪蝙,兩者對(duì)應(yīng)起來(lái),應(yīng)該沒(méi)問(wèn)題逛球。但autorelease雖然會(huì)使引用計(jì)數(shù)減一,但是它并不是立即減一颤绕,它的本質(zhì)功能只是把對(duì)象放到離他最近的自動(dòng)釋放池里。當(dāng)自動(dòng)釋放池銷(xiāo)毀了奥务,才會(huì)向自動(dòng)釋放池中的每一個(gè)對(duì)象發(fā)送release消息。這道題的問(wèn)題就在autorelease氯葬。因?yàn)閘argeNumber是一個(gè)很大的數(shù),autorelease又不能使引用計(jì)數(shù)立即減一溢谤,所以在循環(huán)結(jié)束前會(huì)造成內(nèi)存溢出的問(wèn)題。
解決方案如下:
@autoreleasepool {
for (int i=0; i<largeNumber; i++) {
@autoreleasepool {
Person *per = [[Person alloc] init];
[per autorelease];
}
}
}

在循環(huán)內(nèi)部再加一個(gè)自動(dòng)釋放池世杀,這樣就能保證每創(chuàng)建一個(gè)對(duì)象就能及時(shí)釋放肝集。

什么是ARC:

官方定義:“自動(dòng)引用計(jì)數(shù)(ARC)是一個(gè)編譯器級(jí)的功能,它能簡(jiǎn)化Cocoa應(yīng)用中對(duì)象生命周期管理(內(nèi)存管理)的流程杏瞻⊙眉觯”

Automatic Reference Counting,自動(dòng)引用計(jì)數(shù)忧吟,即ARC

ARC編譯器有兩部分,分別是前端編譯器和優(yōu)化器

當(dāng)ARC開(kāi)啟時(shí)溜族,編譯器將自動(dòng)在代碼合適的地方插入retain, release和autorelease

ARC優(yōu)化器---當(dāng)代碼中出現(xiàn)多個(gè)對(duì) retain 和release的重復(fù)調(diào)用,ARC優(yōu)化器負(fù)責(zé)移出多余的 retain 和release語(yǔ)句煌抒。確保生成的代碼運(yùn)行速度高于手動(dòng)引用計(jì)數(shù)的代碼。

如果涉及到較為底層的東西寡壮,比如Core Foundation中的malloc()或者free()等讹弯,ARC就鞭長(zhǎng)莫及了,這時(shí)候還是需要自己手動(dòng)進(jìn)行內(nèi)存管理

  • 打開(kāi)ARC:-fobjc-arc
  • 關(guān)閉ARC:-fno-objc-arc

關(guān)鍵字:

@property的參數(shù)分為三類(lèi)闸婴,也就是說(shuō)參數(shù)最多可以有三個(gè)

程序會(huì)使用三類(lèi)中的各個(gè)默認(rèn)參數(shù)芍躏,默認(rèn)參數(shù):(atomic,readwrite,assign)

atomic 原子的 對(duì)屬性加鎖邪乍,多線程下線程安全庇楞,默認(rèn)屬性 加同步 是防止在寫(xiě)未完成的時(shí)候被另外一個(gè)線程讀取,造成數(shù)據(jù)錯(cuò)誤吕晌。而這種機(jī)制是耗費(fèi)系統(tǒng)資源的。對(duì)于對(duì)象的默認(rèn)屬性睛驳,就是setter/getter生成的方法是一個(gè)原子操作。
如果有多個(gè)線程同時(shí)調(diào)用setter的話(huà)乏沸,不會(huì)出現(xiàn)某一個(gè)線程執(zhí)行setter全部語(yǔ)句之前,另一個(gè)線程開(kāi)始執(zhí)行setter的情況蹬跃,相關(guān)于方法頭尾加了鎖一樣。

nonatomic 非原子的 對(duì)屬性不加鎖蝶缀,多線程下不安全丹喻,但速度快 不加同步碍论,多線程并發(fā)訪問(wèn)會(huì)提高性能。非原子操作骑冗,就是沒(méi)有鎖,所有的線程都可以一起訪問(wèn)贼涩。

readwrite 默認(rèn)屬性,將生成不帶額外參數(shù)的getter和setter方法(setter方法只有一個(gè)參數(shù))薯蝎。

readonly 將只生成getter方法而不生成setter方法(getter方法沒(méi)有g(shù)et前綴)。

assign 基本的賦值袒哥、直接賦值,默認(rèn)值 不更改索引計(jì)數(shù)(Reference Counting).使用assign: 對(duì)基礎(chǔ)數(shù)據(jù)類(lèi)型 (NSInteger)和C數(shù)據(jù)類(lèi)型(int, float, double, char,等)

retain 讓對(duì)象引用計(jì)數(shù)+1堡称,表示擁有這個(gè)對(duì)象,先release原來(lái)的值却紧,在retain新值

copy 先release原來(lái)的值,在copy新值 建立一個(gè)索引計(jì)數(shù)為1的對(duì)象晓殊,然后釋放舊對(duì)象

retain是指針拷貝,copy是內(nèi)容拷貝巫俺。(可以理解為retain是淺拷貝,copy是深拷貝介汹。)

strong 強(qiáng)引用,strong關(guān)鍵字與retain關(guān)似嘹承,用了它,引用計(jì)數(shù)自動(dòng)+1赶撰,有strong指向的對(duì)象不會(huì)被釋放

weak 弱引用,聲明為weak的指針豪娜,指針指向的地址一旦被釋放餐胀,這些指針都將被賦值為nil瘤载。這樣的好處能有效的防止野指針。聲明了一個(gè)可以自動(dòng) nil 化的弱引用鸣奔,當(dāng)weak指向的內(nèi)存釋放掉后自動(dòng)置為nil,防止野指針挎狸。

unsafe_unretained聲明的指針,由于 self.string1=nil已將內(nèi)存釋放掉了锨匆,但是string2并不知道已被釋放了,所以是野指針茅主。然后訪問(wèn)野指針的內(nèi)存就造成crash. 聲明一個(gè)弱應(yīng)用,但是不會(huì)自動(dòng)nil化诀姚,也就是說(shuō),如果所指向的內(nèi)存區(qū)域被釋放了赫段,這個(gè)指針就是一個(gè)野指針了。

assign瑞佩,用于基本數(shù)據(jù)類(lèi)型

retain聚磺,通常用于非字符串對(duì)象 對(duì)其他NSObject和其子類(lèi)

copy,通常用于字符串對(duì)象瘫寝、block、NSArray焕阿、NSDictionary
copy是創(chuàng)建一個(gè)新對(duì)象,retain是創(chuàng)建一個(gè)指針暮屡,引用對(duì)象計(jì)數(shù)加1

strong強(qiáng)引用也就是我們通常所講的引用,其存亡直接決定了所指對(duì)象的存亡。如果不存在指向一個(gè)對(duì)象的引用钥飞,并且此對(duì)象不再顯示列表中衫嵌,則此對(duì)象會(huì)被從內(nèi)存中釋放。

weak弱引用除了不決定對(duì)象的存亡外楔绞,其他與強(qiáng)引用相同。即使一個(gè)對(duì)象被持有無(wú)數(shù)個(gè)若引用酒朵,只要沒(méi)有強(qiáng)引用指向他,那么其還是會(huì)被清除蔫耽。

什么情況下使用weak關(guān)鍵字,相比assign有什么不同针肥?
1) 在ARC中,在有可能出現(xiàn)循環(huán)引用的時(shí)候慰枕,往往要通過(guò)讓其中一端使用weak來(lái)解決。比如delegate代理
2) 自身已經(jīng)對(duì)它進(jìn)行一次強(qiáng)引用具帮,沒(méi)有必要再?gòu)?qiáng)引用一次,此時(shí)也會(huì)使用weak蜂厅,自定義控件屬性一般也使用weak。
不同點(diǎn):
1)weak此特質(zhì)表明該屬性定義了一種“非擁有關(guān)系”掘猿。為這種屬性設(shè)置新值時(shí),設(shè)置方法既不保留新值稠通,也不釋放舊值。此特性與assign一樣改橘,不同在于它修飾的屬性對(duì)象遭到推毀時(shí),屬性值也會(huì)清空飞主。而assign的“設(shè)置方法”只會(huì)執(zhí)行針對(duì)“純量類(lèi)型” (scalar type高诺,例如 CGFloat 或 NSlnteger 等)的簡(jiǎn)單賦值操作碾篡。
2)assign可以用非OC對(duì)象,而weak必須用于OC對(duì)象耽梅。

static 關(guān)鍵字的作用:

static 一般情況下,只能用NSString或者基本類(lèi)型 都是私有的眼姐,通常在單例中使用

函數(shù)體內(nèi) static 變量的作用范圍為該函數(shù)體,不同于 auto 變量众旗,該變量的內(nèi)存只被分配一次,因此其值在下次調(diào)用時(shí)仍維持上次的值贡歧;
在C語(yǔ)言中滩租,
關(guān)鍵字static有三個(gè)明顯的作用:作用域只限在本地范圍內(nèi)使用利朵。

1). 在函數(shù)體,一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過(guò)程中維持其值不變绍弟。

2). 在模塊內(nèi)(但在函數(shù)體外),一個(gè)被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問(wèn)樟遣,但不能被模塊外其它函數(shù)訪問(wèn)。它是一個(gè)本地的全局變量豹悬。

3). 在模塊內(nèi),一個(gè)被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用瞻佛。那就是,這個(gè)函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用涤久。

關(guān)鍵字const有什么含意?修飾類(lèi)呢?static的作用,用于類(lèi)呢?還有extern c的作用

const 意味著"只讀"响迂, 就是被修飾的不可以再修改蔗彤!
下面的聲明都是什么意思川梅?

1 const int a;

2 int const a;

3 const int *a;

4 int * const a;

5 int const * a const;

前兩個(gè)的作用是一樣贫途,a是一個(gè)常整型數(shù)。

第三個(gè)意味著a是一個(gè)指向常整型數(shù)的指針(也就是丢早,整型數(shù)是不可修改的,但指針可以)怨酝。

第四個(gè)意思a是一個(gè)指向整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是可以修改的农猬,但指針是不可修改的)。

最后一個(gè)意味著a是一個(gè)指向常整型數(shù)的常指針(也就是說(shuō)斤葱,指針指向的整型數(shù)是不可修改的,同時(shí)指針也是不可修改的)揍堕。

結(jié)論:

關(guān)鍵字const的作用是為給讀你代碼的人傳達(dá)非常有用的信息,實(shí)際上鹤啡,聲明一個(gè)參數(shù)為常量是為了告訴了用戶(hù)這個(gè)參數(shù)的應(yīng)用目的蹲嚣。如果你曾花很多時(shí)間清理其它人留下的垃圾,你就會(huì)很快學(xué)會(huì)感謝這點(diǎn)多余的信息隙畜。(當(dāng)然,懂得用const的程序員很少會(huì)留下的垃圾讓別人 來(lái)清理的议惰。) 通過(guò)給優(yōu)化器一些附加的信息,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼言询。
合理地使用關(guān)鍵字const可以使編譯器很自然地保護(hù)那些不希望被改變的參數(shù),防止其被無(wú)意的代碼修改运杭。簡(jiǎn)而言之,這樣可以減少bug的出 現(xiàn)辆憔。

(1)欲阻止一個(gè)變量被改變报嵌,可以使用 const 關(guān)鍵字熊榛。在定義該 const 變量時(shí),通常需要對(duì)它進(jìn)行初始化玄坦,因?yàn)橐院缶蜎](méi)有機(jī)會(huì)再去改變它了;

(2)對(duì)指針來(lái)說(shuō)煎楣,可以指定指針本身為 const,也可以指定指針?biāo)傅臄?shù)據(jù)為 const转质,或二者同時(shí)指定為 const;

(3)在一個(gè)函數(shù)聲明中休蟹,const 可以修飾形參,表明它是一個(gè)輸入?yún)?shù)赂弓,在函數(shù)內(nèi)部不能改變其值;

(4)對(duì)于類(lèi)的成員函數(shù)盈魁,若指定其為 const 類(lèi)型,則表明其是一個(gè)常函數(shù)杨耙,不能修改類(lèi)的成員變量;

(5)對(duì)于類(lèi)的成員函數(shù)珊膜,有時(shí)候必須指定其返回值為 const 類(lèi)型,以使得其返回值不為“左值”车柠。

volatile有什么含意?并給出三個(gè)不同的例子。

一個(gè)定義為 volatile的變量是說(shuō)這變量可能會(huì)被意想不到地改變竹祷,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了塑陵。

精確地說(shuō)就是,優(yōu)化器在用到這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量的值猿妈,而不是使用保存在寄存器里的備份巍虫。

下面是volatile變量的幾個(gè)例子:

并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)

一個(gè)中斷服務(wù)子程序中會(huì)訪問(wèn)到的非自動(dòng)變量(Non-automatic variables)

多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量

ios的@property屬性和@synthesize屬性:

//當(dāng)編譯器遇到@property時(shí)鳍刷,會(huì)自動(dòng)展開(kāi)成getter和setter的聲明

@property int age;

@property int no;

//@synthesize 會(huì)自動(dòng)生成getter和setter的實(shí)現(xiàn)

//@synthesize 默認(rèn)會(huì)去訪問(wèn)age,no输瓜,height同名的變量,

//如果找不到同名的變量尤揣,會(huì)在內(nèi)部自動(dòng)生成一個(gè)私有同名變量age,no北戏,height,嗜愈,

//因此Student.h 中的這幾個(gè)變量也可以省略不寫(xiě)。

@synthesize age,no;

1.在Xcode4.5及以后的版本中蠕嫁,可以省略@synthesize ,編譯器會(huì)自動(dòng)幫你加上getter 和 setter 方法的實(shí)現(xiàn)剃毒,并且默認(rèn)會(huì)去訪問(wèn)_age這個(gè)成員變量,如果找不到_age這個(gè)成員變量赘阀,會(huì)自動(dòng)生成一個(gè)叫做 _age的私有成員變量。

ios中的成員變量定義在@interface 和@implementation 中的區(qū)別是什么基公?

定義在@interface中是指定義在頭文件里, 定義在@implementation中是指在實(shí)現(xiàn)文件中的類(lèi)擴(kuò)展(Class Extensions)酌媒, 一般來(lái)說(shuō)把要公開(kāi)的信息(變量,屬性秒咨,方法)定義在頭文件里, 把要隱藏的信息定義在類(lèi)擴(kuò)展里雨席,只是為了隱藏私有信息, 不需要被外界知道的就不要放在頭文件里陡厘, 這樣可以隔離接口和實(shí)現(xiàn)抽米。

堆和棧糙置?

對(duì)于棧來(lái)講,是由編譯器自動(dòng)管理谤饭,無(wú)需我們手工控制;對(duì)于堆來(lái)講揉抵,釋放工作有程序員控制,容易產(chǎn)生memory Leak冤今。

1.申請(qǐng)方式:stack:由系統(tǒng)自動(dòng)分配。heap:需要程序員自己申請(qǐng)戏罢。

2.申請(qǐng)后系統(tǒng)的響應(yīng)

棧:只要棧的剩余空間大于所申請(qǐng)空間,系統(tǒng)將為程序提供內(nèi)存帖汞,否則將報(bào)異常提示棧溢出。

堆:首先應(yīng)該知道操作系統(tǒng)有一個(gè)記錄空閑內(nèi)存地址的鏈表翩蘸,當(dāng)系統(tǒng)收到程序的申請(qǐng)時(shí)公条,會(huì)遍歷該鏈表啊送,尋找第一個(gè)空間大于所申請(qǐng)空間的堆結(jié)點(diǎn)实胸,然后將該結(jié)點(diǎn)從空閑結(jié)點(diǎn)鏈表中刪除秧耗,并將該結(jié)點(diǎn)的空間分配給程序舶治,

3.申請(qǐng)大小的限制:

棧:在Windows下,棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域霉猛。這句話(huà)的意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的,大小有限制惜浅。

堆:堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)是用鏈表來(lái)存儲(chǔ)的空閑內(nèi)存地址的承绸,自然是不連續(xù)的,而鏈表的遍歷方向是由低地址向高地址

4.申請(qǐng)效率的比較:

棧由系統(tǒng)自動(dòng)分配军熏,速度較快。

堆是由new分配的內(nèi)存羞迷,一般速度比較慢界轩,而且容易產(chǎn)生內(nèi)存碎片,

5.堆和棧中的存儲(chǔ)內(nèi)容

6.存取效率的比較:

棧的效率比較高

堆和棧的區(qū)別?

堆是程序員控制的浊猾,棧是編輯器自動(dòng)管理,棧是一塊連續(xù)的內(nèi)存區(qū)域葫慎,是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),堆是向高低直落站的數(shù)據(jù)結(jié)構(gòu)偷办。

管理方式:對(duì)于棧來(lái)講,是由編譯器自動(dòng)管理椒涯,無(wú)需我們手工控制;對(duì)于堆來(lái)說(shuō)废岂,釋放工作由程序員控制,容易產(chǎn)生memory leak湖苞。

申請(qǐng)大小:

棧:在Windows下,棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)财骨,是一塊連續(xù)的內(nèi)存的區(qū)域。這句話(huà)的意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的隆箩,在WINDOWS下,棧的大小是2M(也有的說(shuō)是1M摘仅,總之是一個(gè)編譯時(shí)就確定的常數(shù)),如果申請(qǐng)的空間超過(guò)棧的剩余空間時(shí),將提示overflow护姆。因此,能從棧獲得的空間較小卵皂。

堆:堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域灯变。這是由于系統(tǒng)是用鏈表來(lái)存儲(chǔ)的空閑內(nèi)存地址的,自然是不連續(xù)的添祸,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計(jì)算機(jī)系統(tǒng)中有效的虛擬內(nèi)存寻仗。由此可見(jiàn),堆獲得的空間比較靈活署尤,也比較大。

碎片問(wèn)題:
對(duì)于堆來(lái)講曹体,頻繁的new/delete勢(shì)必會(huì)造成內(nèi)存空間的不連續(xù),從而造成大量的碎片箕别,使程序效率降低。對(duì)于棧來(lái)講究孕,則不會(huì)存在這個(gè)問(wèn)題,因?yàn)闂J窍冗M(jìn)后出的隊(duì)列厨诸,他們是如此的一一對(duì)應(yīng),以至于永遠(yuǎn)都不可能有一個(gè)內(nèi)存塊從棧中間彈出

分配方式:
堆都是動(dòng)態(tài)分配的微酬,沒(méi)有靜態(tài)分配的堆。棧有2種分配方式:靜態(tài)分配和動(dòng)態(tài)分配颗管。靜態(tài)分配是編譯器完成的,比如局部變量的分配垦江。動(dòng)態(tài)分配由alloca函數(shù)進(jìn)行分配,但是棧的動(dòng)態(tài)分配和堆是不同的,他的動(dòng)態(tài)分配是由編譯器進(jìn)行釋放绽族,無(wú)需我們手工實(shí)現(xiàn)。

分配效率:
棧是機(jī)器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu)吧慢,計(jì)算機(jī)會(huì)在底層對(duì)棧提供支持:分配專(zhuān)門(mén)的寄存器存放棧的地址,壓棧出棧都有專(zhuān)門(mén)的指令執(zhí)行检诗,這就決定了棧的效率比較高。堆則是C/C++函數(shù)庫(kù)提供的逢慌,它的機(jī)制是很復(fù)雜的。

MRC下內(nèi)存管理的缺點(diǎn):
釋放一個(gè)堆內(nèi)存時(shí)涕癣,首先要確定指向這個(gè)堆空間的指針都被release了。(避免提前釋放)
釋放指針指向的堆空間坠韩,首先要確定哪些指向同一個(gè)堆炼列,這些指針只能釋放一次。(避免釋放多次俭尖,造成內(nèi)存泄露)
模塊化操作時(shí),對(duì)象可能被多個(gè)模塊創(chuàng)建和使用稽犁,不能確定最后由誰(shuí)釋放
多線程操作時(shí),不確定哪個(gè)線程最后使用完畢已亥。

雖然ARC給我們編程帶來(lái)的很多好多,但也可能出現(xiàn)內(nèi)存泄露虑椎。如下面兩種情況:
循環(huán)參照: A有個(gè)屬性參照B,B有個(gè)屬性參照A捆姜,如果都是strong參照的話(huà),兩個(gè)對(duì)象都無(wú)法釋放泥技。
死循環(huán): 如果有個(gè)ViewController中有無(wú)限循環(huán),也會(huì)導(dǎo)致即使ViewController對(duì)應(yīng)的view消失了,ViewController也不能釋放簸呈。

什么情況下會(huì)發(fā)生內(nèi)存泄漏和內(nèi)存溢出?
當(dāng)程序在申請(qǐng)內(nèi)存后,無(wú)法釋放已申請(qǐng)的內(nèi)存空間(例如一個(gè)對(duì)象或者變量使用完成后沒(méi)有釋放,這個(gè)對(duì)象一直占用著內(nèi)存)卸亮,一次內(nèi)存泄露危害可以忽略,但內(nèi)存泄露堆積后果很?chē)?yán)重兼贸,無(wú)論多少內(nèi)存,遲早會(huì)被占光。內(nèi)存泄露會(huì)最終會(huì)導(dǎo)致內(nèi)存溢出!
當(dāng)程序在申請(qǐng)內(nèi)存時(shí)吃溅,沒(méi)有足夠的內(nèi)存空間供其使用溶诞,出現(xiàn)out of memory;比如申請(qǐng)了一個(gè)int,但給它存了long才能存下的數(shù)螺垢,那就是內(nèi)存溢出。

runloop枉圃、autorelease pool以及線程之間的關(guān)系。
每個(gè)線程(包含主線程)都有一個(gè)Runloop孽亲。對(duì)于每一個(gè)Runloop,系統(tǒng)會(huì)隱式創(chuàng)建一個(gè)Autorelease pool展父,這樣所有的release pool會(huì)構(gòu)成一個(gè)像callstack一樣的一個(gè)棧式結(jié)構(gòu),在每一個(gè)Runloop結(jié)束時(shí)栖茉,當(dāng)前棧頂?shù)腁utorelease pool會(huì)被銷(xiāo)毀,這樣這個(gè)pool里的每個(gè)Object會(huì)被release吕漂。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市痰娱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌梨睁,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件官辈,死亡現(xiàn)場(chǎng)離奇詭異箱舞,居然都是意外死亡拳亿,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)肺魁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)电湘,“玉大人寂呛,你說(shuō)我怎么就攤上這事〈荆” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵劫拢,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我强胰,道長(zhǎng)舱沧,這世上最難降的妖魔是什么狗唉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮涡真,結(jié)果婚禮上肾筐,老公的妹妹穿的比我還像新娘哆料。我一直安慰自己吗铐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布典阵。 她就那樣靜靜地躺著,像睡著了一般壮啊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上歹啼,一...
    開(kāi)封第一講書(shū)人閱讀 51,208評(píng)論 1 299
  • 那天玄渗,我揣著相機(jī)與錄音,去河邊找鬼藤树。 笑死拓萌,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的微王。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼骂远,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了激才?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤劣挫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后压固,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡靠闭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了愧膀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拦键。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡檩淋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蟀悦,到底是詐尸還是另有隱情,我是刑警寧澤日戈,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站瑞侮,受9級(jí)特大地震影響的圆,放射性物質(zhì)發(fā)生泄漏半火。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一梅掠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阎抒,春花似錦、人聲如沸且叁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纱新。三九已至,卻和暖如春脸爱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背簿废。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留执庐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像迂烁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子盟步,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

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

  • 從上圖可以看到,棧里面存放的是值類(lèi)型却盘,堆里面存放的是對(duì)象類(lèi)型媳拴。對(duì)象的引用計(jì)數(shù)是在堆內(nèi)存中操作的兆览。下面我們講講堆和棧...
    jackyshan閱讀 1,651評(píng)論 2 11
  • Objective-C,顧名思義子巾,是一門(mén)超C的語(yǔ)言,自從ARC(Auto Reference Count)出現(xiàn)了之...
    xiao彰閱讀 469評(píng)論 0 2
  • 馮·諾依曼體系:運(yùn)算器 控制器 存儲(chǔ)器 輸入與輸出 內(nèi)存即存儲(chǔ)器线梗,用來(lái)存儲(chǔ)指令與數(shù)據(jù) 注:哈佛體系與普林斯頓體系的...
    小李龍彪閱讀 656評(píng)論 0 8
  • 自動(dòng)引用計(jì)數(shù) 什么是自動(dòng)引用計(jì)數(shù)內(nèi)存管理/引用計(jì)數(shù)ARC規(guī)則ARC的實(shí)現(xiàn) 1.1 什么是自動(dòng)引用計(jì)數(shù) ARC和MR...
    凡幾多閱讀 899評(píng)論 0 5
  • 高考之后怠益,有很多計(jì)劃,本來(lái)信心滿(mǎn)滿(mǎn)的覺(jué)得自己一定能做到蜻牢,可是理想很豐滿(mǎn),現(xiàn)實(shí)很骨感孩饼。從六月十號(hào)到六月十八號(hào)...
    你的月亮我的爽閱讀 237評(píng)論 0 1