簡單理解下內存的幾大區域


初步了解下介紹

  1.棧區

  棧區(stack)由編譯器自動分配並釋放,存放的是函數的參數值,局部變量等,方法調用的實參也是保存在棧區的。棧是系統數據結構,對應線程/進程是唯一的。優點是快速高效,缺點是有限制,數據不靈活。由編譯器自動分配釋放。主要存放一些基本類型的變量和對象引用類型。

  2.堆區

  由程序員分配和釋放,如果程序員不釋放,可能會出現內存泄露,程序結束的時候,可能會由操作系統回收,比如iOS中alloc都是存放在堆中,優點是靈活方便,數據適應面廣泛,但是效率有一定降低,堆空間的分配總是動態的,不同堆分配的內存無法互相操作。雖然程序結束的時候所有的數據空間都會被釋放回系統,但是精確的申請內存,釋放內存匹配是良好程序的基本要素。主要存放用new構造的對象和數組。

  3.全局區(靜態區)

  全局變量和靜態變量是放在一起的,初始化的全局變量和靜態變量存放在一塊區域,未初始化的全局變量和靜態變量在相鄰的另一塊區域,程序結束后由系統釋放。

  注意:全局區又可分為未初始化全局區:.bss段和初始化全局區:data段。

  舉例:int a;為初始化的 int a = 10 ;已初始化的。

  4.文字常量區 

  存放常量字符串,程序結束后由系統釋放。

  5.代碼區

  存放函數的二進制代碼

  大致如圖所示

 

例子代碼

int a = 10; // 全局初始化區
char *p; //    全局未初始化區

main{
   int b; // 棧區
   char s[] = "abc" // 棧區
   char *p1; //    棧區
   char *p2 = "123456" 123456 在常量區,p2在棧上
   static int c = 0; // 全局(靜態)初始化區
   
   w1 = (char *)malloc(10);
   w2 = (char *)malloc(20);
   分配得來的10和20字節的區域就在堆區。
}

 申請后的系統是如何響應的?

1.棧

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

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

2.堆

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

申請的限制是怎樣的? 

棧:

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

堆:

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

低地址 ------------------> 高地址

代碼區 - 常量區 - 全局區 - 堆區 - 棧區

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

堆:是由alloc分配的內存,速度比較慢,而且容易產生內存碎片,不過使用起來最方便。

打個比喻來說:

使用棧就像去飯館里吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃完了就走,不用理會切菜,洗菜等准備工作和洗完、刷鍋等掃尾工作。他的好處是快捷,但是自由度比較小。

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

這里附上自己的一個簡單的菜譜類的小app的下載地址:

http://itunes.apple.com/cn/app/id533655318?mt=8


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM