一條進程的棧區、堆區、數據區和代碼區在內存中的映射
一條進程的棧區、堆區、數據區和代碼區在內存中的映射
1>棧區:主要用來存放局部變量, 傳遞參數, 存放函數的返回地址。.esp 始終指向棧頂, 棧中的數據越多, esp的值越小。
2>堆區:用於存放動態分配的對象, 當你使用 malloc和new 等進行分配時,所得到的空間就在堆中。動態分配得到的內存區域附帶有分配信息, 所以你 能夠 free和delete它們。
3>數據區:全局,靜態和常量是分配在數據區中的,數據區包括bss(未初始化數據區)和初始化數據區。
注意:
1)堆向高內存地址生長;
2)棧向低內存地址生長;
3)堆和棧相向而生,堆和棧之間有個臨界點,稱為stkbrk。
1、一條進程在內存中的映射
假設現在有一個程序,它的函數調用順序如下:
main(...) ->; func_1(...) ->; func_2(...) ->; func_3(...),即:主函數main調用函數func_1; 函數func_1調用函數func_2; 函數func_2調用函數func_3。
當一個程序被操作系統調入內存運行, 其對應的進程在內存中的映射如下圖所示:
注意:
1>隨着函數調用層數的增加,函數棧幀是一塊塊地向內存低地址方向延伸的;
2>隨着進程中函數調用層數的減少(即各函數調用的返回),棧幀會一塊塊地被遺棄而向內存的高址方向回縮;
3>各函數的棧幀大小隨着函數的性質的不同而不等, 由函數的局部變量的數目決定。
4>未初始化數據區(BSS):用於存放程序的靜態變量,這部分內存都是被初始化為零的;而初始化數據區用於存放可執行文件里的初始化數據。這兩個區統稱為數據區。
5>Text(代碼區):是個只讀區,存放了程序的代碼。任何嘗試對該區的寫操作會導致段違法出錯。代碼區是被多個運行該可執行文件的進程所共享的。
6>進程對內存的動態申請是發生在Heap(堆)里的。隨着系統動態分配給進程的內存數量的增加,Heap(堆)有可能向高址或低址延伸, 這依賴於不同CPU的實現,但一般來說是向內存的高地址方向增長的。
7>在未初始化數據區(BSS)或者Stack(棧區)的增長耗盡了系統分配給進程的自由內存的情況下,進程將會被阻塞, 重新被操作系統用更大的內存模塊來調度運行。
8>函數的棧幀:包含了函數的參數(至於被調用函數的參數是放在調用函數的棧幀還是被調用函數棧幀, 則依賴於不同系統的實現)。函數的棧幀中的局部變量以及恢復該函數的主調函數的棧幀(即前一個棧幀)所需要的數據, 包含了主調函數的下一條執行指令的地址。
2、 函數的棧幀
函數調用時所建立的棧幀包含下面的信息:
1)函數的返回地址。返回地址是存放在主調函數的棧幀還是被調用函數的棧幀里,取決於不同系統的實現;
2)主調函數的棧幀信息, 即棧頂和棧底;
3)為函數的局部變量分配的棧空間;
4)為被調用函數的參數分配的空間取決於不同系統的實現。
注意:
1>bss區(未初始化數據段):並不給該段的數據分配空間,僅僅是記錄了數據所需空間的大小。
2>data(初始化的數據段):為數據分配空間,數據保存在目標文件中。
A 靜態數據區:內存在程序啟動的時候才被分配,而且可能直到程序開始執行的時候才被初始化,如函數中的靜態變量就是在程序第一次執行到定義該變量的代碼時才被初始化。所分配的內存在程序的整個運行期間都存在,如全局變量,static變量等。
注意:初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量與靜態變量在相鄰的另一塊區域,同時未被初始化的對象存儲區可以通過void*來訪問和操縱,程序結束后由系統自行釋放。
B 代碼區:存放函數體的二進制代碼;
C 棧區:存放自動變量。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元由編譯器自動釋放,超出其作用域外的操作沒有定義。棧內存分配運算內置於處理器的指令集中,效率很高,但分配的內存容量有限。棧存放函數的參數值,局部變量的值等。
D 堆區(自由存儲區):在運行的時候調用程序(如C中的malloc或C++中的new)分配內存,可以在任何時候決定分配內存及分配的大小,用戶自己負責在何時釋放內存(如用free或delete)。堆中的所有東西都是匿名的,這樣不能按名字訪問,而只能通過指針訪問。
http://zqwt.012.blog.163.com/blog/static/120446842010113091137224/
棧和堆的區別
管理方式:
棧是由編譯器進行管理,無需我們手動控制.
堆的釋放工作由程序員進行管理,容易產生內存泄露.
申請大小:
棧是向低地址擴展的數據結構,是一塊連續的內存區域,能從棧獲得的空間較小 ,編譯時就確定了大小.
堆是向高地址擴展的數據結構,是不連續的內存區域,堆獲得的空間比較靈活,也比較大.
碎片問題:
棧是先進后出的隊列,不會有內存塊從棧中間彈出.
對於堆來講,頻繁的new/delete勢必會造成內存空間的不連續性,從而造成大量的碎片 ,使程序效率降低.
分配方式:
棧有2種分配方式: 靜態分配和動態分配.
堆都是動態分配.
分配效率:
棧是機器系統提供的數據結構,會在底層對棧提供支持.
堆則是c/c++函數提供的,它的機制比較復雜.