OC第九天:內存管理初級

⼀、內存管理的⽅式。
爲什麼要使⽤內存管理
在⼀個擁有數⼗個甚⾄是上百個類的⼯程⾥,查找內存問題極其困 難。瞭解內存常⻅問題,能幫我們減少出錯⼏率。
內存問題體現在兩個⽅⾯:內存溢出、野指針異常。
內存溢出
iOS給每個應⽤程序提供了⼀定的內存,⽤於程序的運⾏。⼀旦超出內存上限,程序就會Crash。
野指針異常
對象內存空間已經被系統回收,仍然使⽤指針操作這塊內存。野指 針異常是程序crash的主要原因。代碼量越⼤的程序,越難找出出現 野指針的位置。
瞭解內存管理,能幫我們提升程序性能,⼤⼤減少調試bug時間。
內存管理的⽅式
垃圾回收(gc)
MRC(Manual Reference Count)
ARC(Auto Reference Count)
內存管理的⽅式
垃圾回收:程序員只需要開闢內存空間,不需要⽤代碼顯⽰地釋 放,系統來判斷哪些空間不再被使⽤,並回收這些內存空間,以便再 次分配。整個回收的過程不需要寫任何代碼,由系統⾃動完成垃圾回 收。Java開發中⼀直使⽤的就是垃圾回收技術。
Manual Reference Count,⼈⼯引⽤計數:內存的開闢和釋放都由 程序代碼進⾏控制。相對垃圾回收來說,對內存的控制更加靈活,可 以在需要釋放的時候及時釋放,對程序員的要求較⾼,程序員要熟悉 內存管理的機制。
Auto Reference Count,⾃動引⽤計數:iOS 5.0的編譯器特性,它 允許⽤戶只開闢空間,不⽤去釋放空間。它不是垃圾回收!它的本質 還是MRC,只是編譯器幫程序員默認加了釋放的代碼。
iOS的內存管理
iOS⽀持兩種內存管理⽅式:ARC和MRC。
MRC的內存管理機制是:引⽤計數。
ARC是基於MRC的。

⼆、引⽤計數機制,影響計數的各個⽅法。
引⽤計數
C語⾔中,使⽤malloc和free,進⾏堆內存的創建和釋放。堆內存只 有正在使⽤和銷燬兩種狀態。
實際開發中,可能會遇到,兩個以上的指針使⽤同⼀塊內存。C語⾔ ⽆法記錄內存使⽤者的個數。
OC採⽤引⽤計數機制管理內存,當⼀個新的引⽤指向對象時,引⽤ 計數器就遞增,當去掉⼀個引⽤時,引⽤計數就遞減。當引⽤計數到 零時,該對象就將釋放佔有的資源。
影響引⽤計數的⽅法
+alloc
+alloc:開闢內存空間,讓被開闢的內存空間的引⽤計數變爲1。 這是由0到1的過程。
-retain
-retain:引⽤計數加1,如果內存空間之前引⽤計數爲1,ratain之 後變爲2,如果引⽤計數是5,retain之後變爲6。
-copy
-copy:把某⼀內存區域的內容拷⻉⼀份,拷⻉到新的內存空間⾥ 去,被拷⻉區域的引⽤計數不變,新的內存區域的引⽤計數爲1。
-release
-release:引⽤計數減1,如果內存空間之前引⽤計數爲4,release 之後變爲3,如果之前引⽤計數爲1,release之後變爲0,內存被系 統回收。
-autorelease
-autorelease:未來的某⼀時刻引⽤計數減1。如果內存之前引⽤計 數爲4,autorelease之後仍然爲4,未來某個時刻會變爲3。



autoreleasepool的使⽤

通過autoreleasepool控制autorelease對象的釋放。 向⼀個對象發送autorelease消息,這個對象何時釋放,取決於 autoreleasepool。
NSAutoreleasePool *pool= [[NSAutoreleasePool alloc]init];和 [pool release];就像⼀對括號,[xxx autorelease];必須寫在兩者之 間。

[xxx autorelease];出現在了兩者之間,pool就會把接收 autorelease的對象給保存起來(以棧的⽅式,把對象壓⼊棧)

當[pool release];的時候,pool會向之前保存的對象逐⼀發送 release消息(對象出棧,越晚autorelease的對象,越早接收 release消息)。


在iOS5之後,不再推薦使⽤NSAutoreleasePool類,使⽤ @autoreleasepool{}替代。
之前寫在NSAutoreleasePool *pool= [[NSAutoreleasePool alloc]init];和[pool release];之間的代碼,需要寫在 @autoreleasepool{}的⼤括號⾥。
出了⼤括號,⾃動釋放池才向各個對象發送release消息。


三、dealloc⽅法
-dealloc是繼承⾃⽗類的⽅法,當對象引⽤計數爲0的時候,由對 象⾃動調⽤。
我們可以在dealloc中打印⼀句話,驗證對象引⽤計數是否降爲0.
- (void)dealloc{ NSLog(@“%@被銷燬了”,self); [super dealloc]; }


四、內存管理的基本原則。
引⽤計數的增加和減少相等,當引⽤計數降爲0之後,不應該再使 ⽤這塊內存空間。
凡是使⽤了alloc、retain或者copy讓內存的引⽤計數增加了,就需 要使⽤release或者autorelease讓內存的引⽤計數減少。在⼀段代碼 內,增加和減少的次數要相等。

五、掌握copy的實現。
-跟retain不同,⼀個對象想要copy,⽣成⾃⼰的副本,需要實現 NSCopying協議,定義copy的細節(如何copy)。如果類沒有接 受NSCopying協議⽽給對象發送copy消息,會引起crash。
//類方法便利構造器方法使用autorelease
//其他方法需要在外部釋放這是規範
//在實例拷貝方法對計數多大影響
   //僞拷貝
    //淺拷貝
   
//拷貝後兩個對象但是賦值是相同的指向同一地址
    //深拷貝拷貝新對象賦值也是新的
   
//對字符串進行拷貝拷貝結果看字符串這個類如何實現拷貝方法對不可變字符串的拷貝其實相當於直接retain一次
   // 可變字符串拷貝時就是真拷貝了一個新的出來


總結

OC藉助引⽤計數機制去管理內存,凡是使⽤了alloc、copy、retain等⽅ 法,增加了引⽤計數,就要使⽤release和autorelease減少引⽤計數,引⽤ 計數爲0的時候,對象所佔的內存,被系統回收。
autorelease是未來某個時間(出autoreleasepool)引⽤減⼀,不是即時 的。
不是任何對象都可以接收copy消息,只有接受了NSCopying協議的對象 才能接收copy消息。
發佈了33 篇原創文章 · 獲贊 0 · 訪問量 7615
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章