程序的儲存空間布局

2021-08-04 03:57:51 字數 1520 閱讀 3700

詳情參見我的另一篇博文 :linux原始碼解析-記憶體描述符(mm_struct)

以下摘自

一條程序的棧區、堆區、資料區和**區在記憶體中的對映

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)為被呼叫函式的引數分配的空間取決於不同系統的實現。

Linux程序位址空間布局

bss段屬於靜態記憶體分配。通常是指用來存放程式中未初始化的全域性變數和未初始化的區域性靜態變數。未初始化的全域性變數和未初始化的區域性靜態變數預設值是0,本來這些變數也可以放到data段的,但是因為他們都是0,所以為他們在data段分配空間並且存放資料0是沒有必要的。程式在執行時,才會給bss段裡...

c程式儲存空間布局

摘自 c程式一直由下面幾部分組成 1 棧 由編譯器自動分配釋放管理。區域性變數及每次函式呼叫時返回位址 以及呼叫者的環境資訊 例如某些機器暫存器 都存放在棧中。新被呼叫的函式在棧上為其自動和臨時變數分配儲存空間。通過以這種方式使用棧,c函式可以遞迴 呼叫。遞迴函式每次呼叫自身時,就使用乙個新的棧幀,...

c程式儲存空間布局

摘自 c程式一直由下面幾部分組成 1 棧 由編譯器自動分配釋放管理。區域性變數及每次函式呼叫時返回位址 以及呼叫者的環境資訊 例如某些機器暫存器 都存放在棧中。新被呼叫的函式在棧上為其自動和臨時變數分配儲存空間。通過以這種方式使用棧,c函式可以遞迴 呼叫。遞迴函式每次呼叫自身時,就使用乙個新的棧幀,...