iPhone開發記憶體管理

2021-06-14 09:20:06 字數 2690 閱讀 4210

開發iphone 應用程式並不難,基本上就是三個詞 - 「memory, memory, memory」 。iphone os 對記憶體的要求很嚴格,有memory leak ,殺掉; 記憶體使用超限額,殺掉。乙個經過測試的程式,在使用過程中90%以上的崩潰都是記憶體問題造成的。在這裡簡單總結一下object-c 記憶體管理。

基本概念

object-c 的記憶體管理基於引用計數(reference count)這種非常常用的技術。簡單講,如果要使用乙個物件,並希望確保在使用期間物件不被釋放,需要通過函式呼叫來取得「所有權」,使用結束後再呼叫函式釋放「所有權」。「所有權」的獲得和釋放,對應引用計數的增加和減少,為正數時代表物件還有引用,為零時代表可以釋放。

函式獲得所有權的函式包括

alloc - 建立物件是呼叫alloc,為物件分配記憶體,物件引用計數加一。

copy - 拷貝乙個物件,返回新物件,引用計數加一。

retain - 引用計數加一,獲得物件的所有權。

另外,名字中帶有alloc, copy, retain 字串的函式也都認為會為引用計數加一。

釋放所有權的函式包括

release - 引用計數減一,釋放所有權。如果引用計數減到零,物件會被釋放。

autorelease - 在未來某個時機釋放。下面具體解釋。

autorelease

在某些情況下,並不想取得所有權,又不希望物件被釋放。例如在乙個函式中生成了乙個新物件並返回,函式本身並不希望取得所有權,因為取得後再沒有機會釋放(除非創造出新的呼叫規則,而呼叫規則是一切混亂的開始),又不可能在函式內釋放,可以借助autorelease 。所謂autorelease , 可以理解為把所有權交給乙個外在的系統(這個系統實際上叫autorelease pool),由它來管理該物件的釋放。通常認為交給 autorelease 的物件在當前event loop 中都是有效的。也可以自己建立nsautoreleasepool 來控制autorelease的過程。

據蘋果的人說,autorelease效率不高,所以能自己release的地方,盡量自己release,不要隨便交給autorelease來處理。

規則引用計數系統有自己的引用規則,遵守規則就可以少出錯:

獲得所有權的函式要和釋放所有權的函式一一對應。

保證只有帶alloc, copy, retain 字串的函式才會讓呼叫者獲得所有權,也就是引用計數加一。

在物件的 dealloc函式中釋放物件所擁有的例項變數。

iphone 開發過程中,記憶體的使用至關重要。不但要合理分配使用記憶體,還要注意記憶體洩露的問題, 因為記憶體洩露會導致程式由於記憶體不足而崩潰。根據個人開發的經驗來看,在開發iphone程式的過程中,關於記憶體的問題需要注意以下幾點:

記憶體分配、釋放成對出現

使用 alloc 分配的記憶體物件需要在用完後 呼叫release釋放

注意copy,retain,assign操作符的區別

copy, retain操作符賦值的物件和alloc一樣,需要release釋放,否則會導致記憶體洩露

assign 操作符的含義是將物件指向另一物件, 兩者指向的是同一記憶體物件,無需呼叫release釋放

nsarray, nsdictionary, nsmutablearray, nsmutabledictionary等容器類, 在使用這些容器類的時候要注意, 在新增物件到這些類物件時,容器類會自動呼叫一次retain,比如

nsstring* string = [[nsstring alloc] initwithstring:@」test string」]; // refcount = 1

nsarray* array = [nsarray array];

[array addobject:string]; // refcount = 2

[string release]; // refcount = 1

這種情況, 即便string已經呼叫release,但是在加入 array中時已經呼叫了一次retain,注意refcount的變化 簡單介紹一下iphone 或者說objective c對物件的管理機制。 oc中採用一種引用計數refcount的方式來管理記憶體物件,當refcount等於0的時候就會釋放物件所佔的記憶體, 操作符alloc,copy, retain都會將refcount加1表示引用計數增加, 而呼叫release使 refcount自動減1, 當refcount=0時表示該物件已經沒有被引用,可以將其釋放, 之後該物件便不可用

連續重複分配記憶體的過程最好建立自己的自動釋放池 nsautoreleasepool,通常是在for、while等迴圈操作過程中,比如

for( int i=0; i < 100; i++ )

在這種情況下,有2點需要注意,首先如果可能,就把str的分配、釋放放在for迴圈外面, 從而減少記憶體的分配、釋放導致程式效率低下,也利於記憶體**,如上例應該為

nsstring* str = [[nsstring alloc] initwithstring:@」some string」];

for( int i=0; i < 100; i++ )

[str release];

如果實際情況複雜,不能像例子中那樣抽離出迴圈外,需要建立自己的記憶體管理池, 同樣適用於需要大量autorelease物件的過程

nsautoreleasepool * pool = [[nsautoreleasepool alloc] init];

for(int i=0; i < 100; i++ )

[pool release];

iphone記憶體管理 二

2 盡量避免使用autorelease 雖然autorelease非常簡單有用,但是在iphone上一定要謹慎使用,畢竟iphone記憶體相當有限.autorelease可能會導致直接的隱型記憶體洩露.比如使用 nsstring string nsstring stringwithformat va...

iPhone 開發中記憶體管理注意事項 TOP 8

記憶體管理可以說是 iphone 開發中最重要也最令人頭疼的關鍵點。cocoachina 版主 lvyile 總結了記憶體管理中最應注意的事項,分別是 通過分配或複製建立的物件保持計數為 1 假設任何別的方法獲取的物件保持計數為1,而且在自動釋放池中,要想在當前執行範圍外使用該物件,就必須保持它 向...

iphone開發中的記憶體分配

1 記憶體分配 釋放成對出現 2 注意copy,retain,assign操作符的區別 copy,retain同alloc一樣需要release,assign指的是將物件指向另乙個物件 3 nsarray,nsdictionary,nsmutablearray,nsmutabledictionary...