內存管理詳解

來談談內存管理

首先知道內存管理是什麼
應用程序內存管理是在程序運行的時候合理的分配內存(分配內存時不會造成內存泄露等)與清除內存(銷燬一個不用的程序,減少內存使用)

爲什麼要進行內存管理呢
蘋果手機的內存大多都是1G,分配給每個App程序的內存空間有限制,當程序運行時,所佔用的內存較大時,就會收到系統給的內存警告,如果超過所佔用內存超過限制是,會被系統強制關閉的,所以我們需要對應用程序進行內存管理,一個好的App程序會儘可能的減少佔用內存

在OC中有兩個管理內存的模式
MRR(Manual Retain-Release),也被人稱作MRC(Manual Reference Counting,手動引用計數)
ARC(Automatic Reference Counting,自動引用計數)

如何調整
在Build Setting中的Objective-C Automatic Reference Counting設置爲YES即爲ARC

注意點,所有繼承NSObject的對象都需要管理內存,因爲存放在堆裏面,基本數據類型不需要管理內存,因爲放在棧裏面

堆: 一般由程序員分配釋放內存,若程序員不釋放,程序結束時可能由OS釋放,其操作方式類似於數據結構中的鏈表
棧: 由操作系統自動分配釋放,存放函數的參數值,局部變量值等,其操作方式類似於數據結構中的棧(先進後出)

在iOS5以前,程序都需要手動添加retain,release,atorelease來管理對象的內存

當使用alloc、new、copy、mutableCopy創建一個新對象時,該新對象的引用計數器爲1
當給對象發送一條retain消息時,對象的引用計數器+1(方法返回對象本身)
當給對象發送一條release消息時對象的引用計數器-1(方法無返回值)
當給對象發送一條retainCount消息時,返回對象的當前引用計數器(不要以該數據來判斷對象是否被釋放)

注意點:
對對象發送一個release消息,不代表對象會釋放,只有對象的引用計數器爲0時纔會被釋放

在內存管理中,會產生將是對象,野指針,空指針
殭屍對象: 所佔用的內存已經被回收的對象,殭屍對象不能再使用
野指針: 指向殭屍對象的指針,給野指針發送消息會報錯EXC_BAD_ACCESS錯誤:訪問了一塊已經被回收的內存
空指針: 沒有指向任何對象的指針(存儲的東西是nil,NULL,0),給空指針發送消息不會報錯,系統什麼也不會做,所以在對象被釋放時將指針設置爲nil可以避免野指針錯誤

殭屍對象,Xcode是不會主動監聽的,需要我們自己去打開
步驟很簡單,
對象步驟爲: Edit Scheme ->; Run ->; Diagnostics ->; Objective-C的Enable Zombie Objects打鉤

Dog *D = [[Dog alloc] init]; // 引用計數器 = 1
[D release]; // 引用計數器 - 1 = 0,指針所指向的對象的內存被釋放
[p release]; // 這句給野指針發送消息,會報野指針錯誤,開啓監聽殭屍對象會給出錯誤信息**- -[Person release]: message sent to deallocated instance 0x100206fd0

自動釋放池的概括
自動釋放池提供了延遲放棄一個對象的所有權的機制,比如想要在一個方法中返回一個對象,如果先使用release放棄了該對象的所有權,那麼return返回的對象便是一個殭屍對象,如果先進行return返回,那麼便無法放棄該對象的所有權,導致了內存泄漏

autorelease是一種支持引用計數的內存管理方式,只要在自動釋放池中給對象發送一條autorelease消息,就會將對象放到自動釋放池中,當自動釋放池被銷燬時,會對池中的所有對象發送一條release消息

autorelease方法會返回對象本身
autorelease方法不會修改對象的引用計數器
autorelease方法可以讓開發者不用實時關心什麼時候發送release消息

類工廠方法內存管理
在開發中,我們經常使用Foundation框架中的類,在調用其類工廠方法創建一個對象時,因爲並不是使用alloc,new,copy或者mutableCopy方法創建的,所以並不需要我們自己在給該對象發送release或者autorelease消息,這是因爲類工廠方法內部都已經在返回對象前進行過延遲釋放

我們在自己書寫類工廠方法時,也應該與系統處理方式相同,快速返回一個autorelease對象的方式具體如下
+ (instancetype)person
{
// 使用self而不是使用Person是因爲這樣可以在子類調用該方法時會返回子類的對象
return [[[self alloc] init] autorelease];
}

快速返回一個帶有參數的autorelease對象的方式具體如下
+ (instancetype)personWithName:(NSString *)name
{
Person *person = [[[self alloc] init] autorelease];
person.name = name;
return person;
}

ARC的概括
ARC是iOS4引入的一項新技術(從iOS5開始支持弱引用),其使用與MRR&MRC相同的內存管理規則來管理內存,不過編譯器會在編譯階段自動的插入retain、release和autorelease等內存管理代碼來管理內存不再需要程序人員手動管理.非常方便,所以現在用的都是ARC模式

多人開發時需要注意的
1> 使用Analyze進行代碼的靜態分析
2> 爲避免不必要的麻煩, 多人開發時儘量使用ARC

和MRC相比消除了手動管理內存的煩惱,不需要手動調用retain,release和aytorelease等方法來管理內存
編譯器還會在適當的位置上插入代碼

在ARC和MRC的屬性修飾符

strong用於OC對象,相當於MRC中的retain
weak用於OC對象,相當於MRC中的assign
assign用於基本數據類型,相當於MRC中的assign

在什麼情況下會發生內存泄露
1> 當程序在申請內存後,無法釋放已申請的內存空間(例如一個對象或者變 量使用完成後沒有釋放,這個對象一直佔用着內存),一次內存泄露危害 可以忽略,但內存泄露堆積後果很嚴重,無論多少內存,遲早會被佔光。

2> 內存泄露會最終會導致內存溢出! 當程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;比如申請了一個int,但給它存了long才能存下的數,那就是內存溢出。

iOS內存管理之Copy
概述
copy(複製、拷貝)是產生一個副本對象的過程,只要是通過拷貝產生的副本對象,副本對象中的內容與源對象中的內容就完全一致,下面介紹幾個copy相關的知識點

copy的特點
修改源對象的屬性和行爲,不會影響副本對象
修改副本對象的屬性和行爲,不會影響源對象
copy與mutableCopy
使用copy產生的副本對象是不可變的(如NSString,NSArray)
使用mutableCopy產生的副本對象是可變的(如NSMutableString,NSMutableArray)
通過拷貝是否會產生新的對象
通過拷貝是否會產生新對象,就要看源對象與副本對象是否滿足拷貝的特點

可變對象通過mutableCopy,會生成新的對象
可變對象通過copy,會生成新的對象
不可變對象通過mutableCopy,會生成新的對象
不可變對象通過copy,不會生成新的對象(因爲源對象與副本對象都是不可變的,已經滿足拷貝的特點)
深拷貝(內容拷貝)與淺拷貝(指針拷貝)
深拷貝: 如果通過拷貝生成了新對象,就稱爲深拷貝(內容拷貝)
淺拷貝: 如果通過拷貝沒生成新對象,就稱爲淺拷貝(指針拷貝)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章