iOS程序中的內存分配 棧區 堆區 全局區(靜態區) 常量區 方法區

在計算機系統中,運行的應用程序的數據都是保存在內存中的,不同類型的數據,保存的內存區域不同。
一、內存分區

  1. 棧區(stack) 由編譯器自動分配並釋放,存放函數的參數值,局部變量(Char Int Float Double基本數據類型在棧裏面)等。棧是系統數據結構,對應線程/進程是唯一的。大概1M左右
    優點是快速高效,缺點時有限制,數據不靈活。[先進後出執行的]

    在棧區中的變量名實際上是棧區的指針別名,沒有使用*,方便我們快速找到變量

    由系統自動分配,速度較快,不會產生內存碎片

    棧空間分靜態分配 和動態分配兩種。

     靜態分配是編譯器完成的,比如自動變量(auto)的分配。
     動態分配由alloca函數完成。
     棧的動態分配無需釋放(是自動的),也就沒有釋放函數。
     爲可移植的程序起見,棧的動態分配操作是不被鼓勵的!
  2. 堆區(heap) 如果是MRC由程序員分配和釋放,ARC系統回收 ,比如在ios 中 alloc 都是存放在堆中。
    優點是靈活方便,數據適應面廣泛,但是效率有一定降低。[順序隨意]

    堆(系統內存加上所有的系統緩存+磁盤)

    堆中的數據是通過一個鏈表管理的,所以如果使用別名的話就比較費勁,所以堆裏面的對象沒別名只有指針

     堆是函數庫內部數據結構,不一定唯一。
     不同堆分配的內存無法互相操作。
     堆空間的分配總是動態的

    雖然程序結束時所有的數據空間都會被釋放回系統,但是精確的申請內存,釋放內存匹配是良好程序的基本要素。

  3. 全局區(靜態區) (static) 全局變量和靜態變量的存儲是放在一起的,初始化的全局變量和靜態變量存放在一塊區域,未初始化的全局變量和靜態變量在相鄰的另一塊區域,程序結束後有系統釋放。

    注意:全局區又可分爲未初始化全局區:
         .bss段和初始化全局區:data段。
         舉例:int a;未初始化的。int a = 10;已初始化的。

    例子代碼:

      int a = 10;  全局初始化區
      char *p;  全局未初始化區
    
     main{
       int b; 棧區
       char s[] = "abc" 棧
       char *p1; 棧 
       char *p2 = "123456";  123456\\\\0在常量區,p2在棧上。
       static int c =0; 全局(靜態)初始化區 
    
       w1 = (char *)malloc(10); 
       w2 = (char *)malloc(20); 
       分配得來得10和20字節的區域就在堆區。 
     }
  4. 文字常量區 存放常量字符串,程序結束後由系統釋放
  5. 程序代碼區 存放函數的二進制代碼

二、申請後的系統響應

  1. 棧:存儲每一個函數在執行的時候都會向操作系統索要資源,棧區就是函數運行時的內存,棧區中的變量由編譯器負責分配和釋放,內存隨着函數的運行分配,隨着函數的結束而釋放,由系統自動完成。

    注意:只要棧的剩餘空間大於所申請空間,系統將爲程序提供內存,否則將報異常提示棧溢出。

  2. 堆:
    1.首先應該知道操作系統有一個記錄空閒內存地址的鏈表。
    2.當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序。
    3 .由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部分重新放入空閒鏈表中 

三、 申請大小的限制

  1. 棧:棧是向低地址擴展的數據結構,是一塊連續的內存的區域。是棧頂的地址和棧的最大容量是系統預先規定好的,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數 ) ,如果申請的空間超過棧的剩餘空間時,將提示overflow。因此,能從棧獲得的空間較小。

  2. 堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閒內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。


    內存分配.png

棧:由系統自動分配,速度較快,不會產生內存碎片
堆:是由alloc分配的內存,速度比較慢,而且容易產生內存碎片,不過用起來最方便

打個比喻來說: 

使用棧就象我們去飯館裏吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等準備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。 

使用堆就象是自己動手做喜歡吃的菜餚,比較麻煩,但是比較符合自己的口味,而且自由度大。

 

文/Liwjing(簡書作者)
原文鏈接:http://www.jianshu.com/p/f3c1b920e8eb

總結iOS中的堆和棧的區別

管理方式:

對於棧來講,是由編譯器自動管理,無需我們手工控制;對於堆來講,釋放工作有程序員控制,容易產生memory Leak。

申請大小:

棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存區域。這句話的意思是棧頂上的地址和棧的最大容量是系統預先規定好的,在Windows下,棧的大小是2M(也有的說1M,總之是編譯器確定的一個常數),如果申請的空間超過了棧的剩餘空間時候,就overflow。因此,能獲得棧的空間較小。

堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閒內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大笑受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。

碎片的問題:

對於堆來講,頻繁的new/delete勢必會造成內存空間的不連續,從而造成大量的碎片,使程序效率降低。對於棧來講,則不會存在這個問題,因爲棧是先進後出的隊列,他們是如此的一一對應,以至於永遠都不可能有一個內存快從棧中彈出。

 

分配方式:

堆都是動態分配的,沒有靜態分配的堆。棧有兩種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,比如局部變量的分配。動態分配是有alloc函數進行分配的,但是棧的動態分配和堆是不同的,他的動態分配由編譯器進行釋放,無需我們手工實現。

分配效率:

棧是機器系統提供的數據結構,計算機會在底層堆棧提供支持,分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是C/C++函數庫提供的,他的機制是很複雜的。

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