iPhone開發記憶體管理

來源:互聯網
上載者:User

原文地址:http://flandycheng.blog.51cto.com/855176/559397

開發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++ )  {  NSString* str = [[NSString alloc] initWithString:@”some string”];  // 針對str的操作  [str release];  }  在這種情況下,有2點需要注意,首先如果可能,就把str的分配、釋放放在for迴圈外面, 從而減少記憶體的分配、釋放導致程式效率低下,也利於記憶體回收,如上例應該為  NSString* str = [[NSString alloc] initWithString:@”some string”];  for( int i=0; i < 100; i++ ){  // 針對str的操作  }  [str release];  如果實際情況複雜,不能像例子中那樣抽離出迴圈外,需要建立自己的記憶體管理池, 同樣適用於需要大量autorelease對象的過程  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  for(int i=0; i < 100; i++ )  {  // actions  }  [pool release];  之所以要這樣做,是因為apple處理iPhone的記憶體管理機制問題, 通常情況下,系統會在需要的時候釋放整理所有的autorelease對象,這就是為什麼有時候autorelease對象在範圍範圍外還有可能是有效  避免不常用對象駐留記憶體, 案頭開發的tx很多喜歡在程式初始化的時候將某些資源比如小圖片載入進記憶體,從而提高程式運行效率。 但這種方式在iPhone以及其它mobile行動裝置開發時需要避免,因為對於這些裝置來說,記憶體永遠顯得不足(當然普通pc記憶體也是越大越好:) )。 按照apple的官方說法, Load resources lazily . 就是在需要的時候再從硬碟上讀取,而避免常駐記憶體。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.