iOS 內(nèi)存管理及區(qū)域分布

在iOS開發(fā)過程中,為了合理的分配有限的內(nèi)存空間,將內(nèi)存區(qū)域分為五個區(qū),由低地址向高地址分類分別是:代碼區(qū)、常量區(qū)、全局靜態(tài)區(qū)、堆、棧。

  • 代碼區(qū)

用來存放函數(shù)的二進(jìn)制代碼,在運(yùn)行時(shí)要防止被非法修改,只允許讀取不允許操作

  • 常量區(qū)

存儲常量數(shù)據(jù),通常程序結(jié)束后由系統(tǒng)自動釋放

  • 全局靜態(tài)區(qū)

全局區(qū)又可分為未初始化全局區(qū):.bss段和初始化全局區(qū):data段。全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域,在程序結(jié)束后有系統(tǒng)釋放。

  • 堆(heap)

由程序員分配和釋放,若程序員不釋放,程序結(jié)束時(shí)可能由OS回收。堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域,以鏈表的方式進(jìn)行存儲。

  • 棧(stack)

棧是由編譯器自動分配并釋放,存放函數(shù)的參數(shù)值,局部變量的值等。棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域,采用后進(jìn)先出(LIFO )。

內(nèi)存管理

  • 內(nèi)存管理的概念

在OC中引入的內(nèi)存管理的作用是什么?

通常比如創(chuàng)建一個OC對象、定義一個變量、調(diào)用一個函數(shù)或者方法都會占用內(nèi)存空間;一個應(yīng)用程序所使用的內(nèi)存是有限的,如果程序占用內(nèi)存過大,系統(tǒng)可能會強(qiáng)制關(guān)閉程序,造成程序崩潰、閃退現(xiàn)象,影響用戶體驗(yàn)。所以,我們需要進(jìn)行合理的分配內(nèi)存、清除內(nèi)存,回收那些不需要再使用的對象。從而保證程序的穩(wěn)定性。

上述講到,堆和棧的原則,首先棧是由編譯器自動分配釋放的,因此棧不需要程序員去做內(nèi)存管理。堆是由程序員手動釋放,因此需要對這塊區(qū)域進(jìn)行管理內(nèi)存。

棧是連續(xù)的存儲空間,且棧的大小是有限的,采用后進(jìn)先出有序的創(chuàng)建和釋放,因此棧排序不會出現(xiàn)不連續(xù)和內(nèi)存浪費(fèi)現(xiàn)象。堆是不連續(xù)的存儲內(nèi)存區(qū)域,是以鏈表的方式存儲。當(dāng)創(chuàng)建對象時(shí),會尋找大于或等于申請的heap 節(jié)點(diǎn)長度的內(nèi)存空間,頻繁的創(chuàng)建和刪除內(nèi)存塊勢必會造成內(nèi)存空間的不連續(xù),從而造成大量的碎片,使程序效率降低。由此引入內(nèi)存管理的概念,以保證高效、快速的分配內(nèi)存,并且在適當(dāng)?shù)臅r(shí)候釋放和回收內(nèi)存資源。

  • 引用計(jì)數(shù)機(jī)制的概念

在OC中,數(shù)據(jù)類型主要分為基本數(shù)據(jù)類型和OC數(shù)據(jù)類型;其中基本數(shù)據(jù)類型存放在棧中,例如:int, float, double,此類數(shù)據(jù)系統(tǒng)可以自動回收,因此無需對其進(jìn)行內(nèi)存管理。OC對象類型存放在堆中,對于任何繼承NSObject的對象,例如:NSString, NSArray等,此類存放需要程序員分配釋放。那么程序員該怎么進(jìn)行管理呢?那就是我們經(jīng)常被熟知的引用計(jì)數(shù)機(jī)制。

引用計(jì)數(shù)機(jī)制是個抽象的概念,為了回收不再被使用的對象,從而減少內(nèi)存空間被占用,系統(tǒng)通過引用計(jì)數(shù)的值來告訴系統(tǒng),該對象是否還有用。當(dāng)對象引用計(jì)數(shù)大于0時(shí),說明該對象依然還被使用,此時(shí)不會被回收;當(dāng)對象的引用計(jì)數(shù)為0時(shí),說明該對象已經(jīng)沒有再持有或被持有,則對象會被系統(tǒng)回收,釋放掉內(nèi)存空間;

什么時(shí)候會產(chǎn)生引用計(jì)數(shù)變化呢?

  • 使用alloc、new、copy、mutableCopy這四個關(guān)鍵字創(chuàng)建的對象,自身引用計(jì)數(shù)為1
  • 引用到該對象需要發(fā)送一條retain消息,使引用計(jì)數(shù)器值+1,說明該對象存在
  • 該對象不再持有或被持有時(shí),發(fā)送一條release消息,使引用計(jì)數(shù)值-1,說明該對象不存在
  • 引用計(jì)數(shù)值為0時(shí),說明對象不再被使用,調(diào)用delloc方法,將該對象釋放掉。
- (void)test {
    @autoreleasepool {
    // 使用alloc創(chuàng)建一個對象,引用計(jì)數(shù)為1
    Person *per = [ [Person alloc] init];
    // 使用retain引用計(jì)數(shù)+1,此時(shí)引用計(jì)數(shù)為2
    [per retain]; 
    // 使用retain引用計(jì)數(shù)-1,此時(shí)引用計(jì)數(shù)為1
    [per release];

    // 引用計(jì)數(shù)為0的對象內(nèi)存被釋放掉
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容