一個32位的運行在保護模式下應用程式,無論是Linux 還是Windows 都給它分配一個4GB的平坦的記憶體空間
一個運行著的c程式所佔用的記憶體空間分為:
代碼區 初始化資料區 未初始化資料區 堆區 和 棧區 在地址上從高位到地位為
(高位)
棧區
堆區
未初始化資料區(即BBS)
資料區
代碼區
(低位)
棧區存放函數的參數值、局部變數的值 ,
由編譯器自動分配釋放
比如實現函數的遞迴調用
堆區用於動態分配記憶體,一般由程式員來分配釋放
下面用一斷代碼來展示c程式記憶體配置
//main.cint a = 0; //a是全域變數 在已初始化區char *p1; //p1在BBS區(未初始化資料區)main() {int b; //b在棧區char s[] = "abc"; //s為陣列變數 在棧區//“abc”是字串常量 在已初始化資料區char *p1,p2; //p1 p2都在棧區char *p3 = "123456"; //p3在棧區 “123456”在已初始化資料區static int c = 0; //c為全域待用資料 存在於已初始化資料區//待用資料會自動初始化p1 = (char *)malloc(10); //新分配的10個位元組位於堆區p2 = (char *)malloc(20); //新分配的20個位元組位於堆區free(p1);free(p2);}
--------------------------------------------------------------------------------------------------------------------------------
C程式一直由下面幾部分組成:
(1) 棧
由編譯器自動分配釋放管理。局部變數及每次函數調用時返回地址、以及調用者的環境資訊(例如某些機器寄存器)都存放在棧中。新被調用的函數在棧上為其自動和臨時變數分配儲存空間。通過以這種方式使用棧,C函數可以遞迴調用。遞迴函式每次調用自身時,就使用一個新的棧幀,因此一個函數調用執行個體中的變數集不會影響另一個函數調用執行個體中的變數。
a.局部變數
b.函數調用時返回地址
c.調用者的環境資訊(例如某些機器寄存器)
(2) 堆
需要由程式員分配釋放管理,若程式員不釋放,程式結束時可能由OS回收。通常在堆中進行動態儲存裝置分配。
如程式中的malloc, calloc, realloc等函數都從這裡面分配。堆是從下向上分配的。
(3) 非初始化資料區段
通常將此段稱為bss段,這一名稱來源於早期組譯工具的一個操作符,意思是“block started by symbol(由符號開始的塊)”,未初始化的全域變數和靜態變數存放在這裡。在程式開始執行之前,核心將此段初始化為0。函數外的說明:long sum[1000] ; 使此變數存放在非初始化資料區段中。
a.未初始化的全域變數
b.未初始化的靜態變數
(4) 初始化的資料
通常將此段稱為資料區段,它包含了程式中需賦初值的變數。初始化的全域變數和靜態變數存放在這裡。例如,C程式中任何函數之外的說明:int maxcount = 99; 使此變數以初值存放在初始化資料區段中。
a.初始化的全域變數
b.初始化的靜態變數
(5) 本文段
CPU執行的機器指令部分。通常,本文段是可共用的,所以即使是經常環境指標環境表環境字串執行的程式(如文本編輯程式、C編譯器、s h e l l等)在儲存空間中也只需有一個副本,另外,本文段常常是唯讀,以防止程式由於意外事故而修改其自身的指令。
下面的記憶體結構顯示了這些段的典型安排:
下面給出一般的c程式儲存布局的典型安排:
使用者空間的程式使用低2G的虛擬記憶體,核心空間使用高2G
高地址 ——0x7FFFFFFF———
命令列參數和環境變數
——————————
棧空間,向下增長
___________________
堆空間,向上增長
———————————
未初始化的資料
———————————
已初始化的資料
———————————
本文段
低地址 ——0x00000000————
可以注意到未初始化的資料區段的內容並不放在磁碟上的程式檔案中,因為,在程式開始運行前他們都被設定為0。需要存放在程式檔案中的只有本文段和初始化資料區段。