記憶體管理初級

2021-06-22 16:24:45 字數 3558 閱讀 4472

一.記憶體分為五大區 :棧區,堆區,全域性區,常量區,**區

2.棧區特點:  

3.堆區的特點

4.常量區的特點

5,全域性區 特點

二.記憶體管理

1.manul reference count  &  auto reference count   (mrc &arc)     referencecount 引用計數 系統根據引用計數的個數來**記憶體  

要注意 引用計數 是為了管理記憶體 (1.防止出現野指標.  2.防止記憶體洩露)

2.幾個記憶體管理的要用到的方法:+ alloc  -retain  -release -copy -autorelease

(1) +alloc (referencecount)由0-1的過程

(2) -retain  ( +1   返回位址  )

person *person1=[person retain]; person 所指物件的引用計數加一

(3)-release (-1    無返回值  )  

[person1 release]; person1所指物件的引用計數減一

(4)-copy  (本身引用計數不變,副本引用計數加一  返回新位址)

person *p2=[p copy];p 所指物件的引用計數不變  p2所指物件的引用計數加一

(5)-autorelease  在將來的某個時間將引用計數減一 注意 autorelease 之後 對系那個的 retaincount 不會馬上減一 而是在將來某個時間減一 (這取決於他處於的 autoreleasepool什麼時候釋放).

3.delloc   是由父類繼承過來的類,有系統自動呼叫,當 物件 的引用計數值為0時,系統會自動呼叫 delloc (自己可以重寫個 delloc 方法用於判斷物件是否銷毀);

注意的一點是[super delloc]表示現在要呼叫從父類繼承過來的 delloc 方法  (注意 :這一句話要放在方法體的最後邊);

在 dealloc 方法中要將所有 有retain屬性 的例項變數 都 release   然後要使用[super dealloc]; 4.

autoreleasepool 的工作原理  就像乙個棧,哪個物件先被放進 pool ,哪個物件就最後 release (棧中存的是物件的位址,即這一塊要釋放的記憶體的位址)

autoreleasepool  目前的建立方式是@ autoreleasepool

autoreleasepool中可以巢狀多個 autoreleasepool{}以便釋放在程式中多次出現的有 autorelease 方法 的物件,避免記憶體空間不足,造成洩露.

5.記憶體管理的原則:

(1).引用計數的增加和減少相等,當引用計數降為0之後,不應該再使用這塊記憶體

(2).凡是使用(要理解為看到了,沒有看到就不減)了 alloc,retain,或者 copy 讓記憶體的引用計數增加了,就需要使用 release或者 autorelease 讓記憶體的引用計數減少.在一段**內,增加和減少的次數要相等.當引用計數值為0 時 ,物件所佔的記憶體,就被系統**

(3).在乙個中referencecount 的增加的次數要和減少的次數一樣.有兩個原因:

(4) 在乙個

內如果有明顯的出現了

alloc retain copy, 

則一定要在這段**結束之前

release.  

要保證每乙個

{}中的+和

-平衡.如果沒有明顯的出現

,就不要用

release,

比如便利構造器

(它的釋放

最好是在自己的實現體中

用autorelease  

延遲釋放 );

6.copy 屬性: 當乙個類要使用 copy時, 生成自己的關於那個物件的副本 就一定要實現 nscopying 協議  並且實現 nscopying 協議中的 - copywithzone:方法  .

並且在這個方法中自己實現 copy 的細節   一般式要建立乙個新的物件,將 self 的值賦給這個物件 然後返回這個物件的位址

例:@inte***ce person:nsobject

……..

@end

@implementation person

- (id)copywithzone:(nszone *)zone

@end

person *p=[[person alloc] initwithname:self.name age:self.age gender:self.gender];

person *p2=[p copy];

copy 

內部的alloc

不在內部釋放

不然在外面看到

copy 

時會又釋放

一次注意:如果  沒有實現 nscopying 協議 而直接使用 copy 方法 就會引發crash   

不是任何物件都可以接收 copy 訊息只有接受了 nscopying 協議的物件才能接收 copy 訊息

7.關於淺拷貝 與 深拷貝  

淺拷貝 與 深拷貝 根據自己的理解 其實並沒有乙個完整的定論.  

一般的理解是 淺拷貝-----只是實現了」指標" 的拷貝  (內容共用,乙個物件中內容的改變 會 導致另乙個物件中內容的改變)

深拷貝—---至少有一層物件實現了產生物件的副本  (內容不共用, 乙個物件中內容的改變,不會影響另乙個物件)

完全拷貝———每一層都實現了物件的副本的產生(類中每乙個例項變數都實現了深拷貝(每一層物件都是))

其實 關於深拷貝 與淺拷貝 只是乙個理解或者概念上的問題  不需要深究什麼是深拷貝,什麼是淺拷貝  他們只是幾種拷貝方式

8.如果出現

兩個物件相互引用的情況(如: husband 中存在 wife 物件 ,wife 中存在 husband 物件) 此時物件作為例項變數的屬性的 attribute 的設定不應該兩個物件同時都設定為 retain 或 copy,  否則會造成 retain cycle ,導致兩個物件都無法 dealloc .  解決辦法是將乙個類的例項變數設定為 assign 表示弱引用, 但這種方法要注意記憶體管理與野指標情況.

同時要注意

**委託的情況,當出現**的情況的時候,**的語義屬性要設定為 assign 防止**與其委託之間的迴圈引入,而導致無法釋放

最終乙個設定語義屬性的乙個基本規則是:  屬性的型別凡是沒有帶 * 都要設定為 assign (包括**的 id 型別);

我們常見的

delegate

往往是assign

方式的屬性而不是

retain

方式的屬性,賦值不會增加引用計數,就是為了防止

delegation

兩端產生不必要的迴圈引用。如果乙個

uitableviewcontroller 物件a

通過retain

獲取了uitableview物件b

的所有權,這個

uitableview物件b

的delegate又是a

,如果這個

delegate

是retain

方式的,那基本上就沒有機會釋放這兩個物件了。自己在設計使用

delegate

模式時,也要注意這點。

OC 記憶體管理初級

法則 如果對乙個物件進行了alloc retain copy之後,就擁有了該物件的所有權,就必須對它進行release或者autorelease alloc 引用計數0 1 retain 引用計數 立即 1 copy release 引用計數 立即 1 autorelease 配合 autorele...

OC記憶體管理初級演練

alloc 開闢記憶體空間,並且將物件的引用計數由0變1.person per1 person alloc init 0 1 retaincount 用來獲取當前物件的引用計數 nslog lu per1 retaincount retain 將物件的引用計數加一 person per2 per1 ...

oc的記憶體管理初級

建立乙個person類在.h,宣告屬性 凡是語義設定使用了retain copy的屬性,其對應的例項變數都需要在dealloc方法裡面release一次 property nonatomic copy nsstring hobby property nonatomic retain nsstring...