C程式的記憶體分布

2021-07-02 19:12:08 字數 4124 閱讀 8753

目錄

1.c程式記憶體分布

2.示例詳解

2.1檢視記憶體分布

2.2未初始化全域性變數

2.3未初始化靜態變數

2.4已初始化靜態變數

2.5初始化全域性變數

乙個典型的c程式的記憶體布局包含下面幾個部分:

1) text segment/code segment (文字/**段)

2) initialized data segment (已初始化資料段)

3) uninitialized data segment/bss(block started by symbol) (未初始化資料段)

4) stack (棧)

5) heap (堆)

乙個正在執行的程序的典型記憶體分布:

1. text segment/code segment(文字/**段)

文字段,也稱之為**段或者文字,它是乙個程式記憶體的一部分,包含可執行指令。

做為一塊記憶體區域,文字段一般處於堆/棧之下,以防止堆/棧將其記憶體覆蓋了。

通常文字段是可以共享的,這樣對於需要經常執行的程式,只需要乙份copy存在於記憶體中。例如文字編輯器,c編譯器,shell等。

另外,文字段一般是唯讀的,防止外邊程式修改其指令。

2. initialized data segment(已初始化資料段)

已初始化資料段,通常簡稱為資料段。包括乙個程式中已經被初始化過的全域性變數以及靜態變數。

注意:資料段不是唯讀的,因為變數值在執行過程中可能會被更改。

資料段可以進一步分為已初始化的唯讀區,以及已初始化的讀寫區。

示例1:c程式中的全域性字串 char s = "hello world",以及main函式之外的c宣告debug=1,都將儲存在讀寫區。

示例2:const char *string = "hello world", 乙個全域性的c宣告,會使得字串"hello world"儲存在唯讀區,指標string儲存在讀寫區。

示例3: static int i = 10;  全域性的int i = 10;    已初始化的靜態資料和全域性資料,也會儲存在此區域。

3. uninitialized data segment/bss (未初始化資料段)

未初始化資料段,常稱為"bss"段。以乙個古老的組合語言操作符命名,表示"block started by symbol". 這個段裡邊的資料會在程式開始執行前被核心初始化為算術0。

bss段位於(初始化)資料段之後,包含所有的全域性變數,以及初始化為0或者沒有被顯示初始化的靜態變數。

例如:static int i;   全域性的int j;     像這些未初始化的靜態或全域性資料,會儲存在此區域。

4. stack

棧區通常是與堆區相鄰的,並且是相反方向增長;當棧指標與堆指標重合時,表示剩餘記憶體已經全部耗盡(在現代的大記憶體空間和虛擬記憶體技術的背景下,棧記憶體可能任意分配,但是總體上任然是反方向增長)。

棧區包含程式棧,是乙個lifo(後進先出)結構,通常位於記憶體的高位址部分。在通常的x86架構體系中,往位址0方向增長;在其他的一些架構中,往反方向增長。

乙個「棧指標"指向棧頂;每次當push乙個值到棧中時,棧指標會調整。壓入乙個函式呼叫的所有的值稱為乙個」棧幀";乙個"棧幀"至少包含乙個返回位址。

棧用於儲存自動變數,函式每一次呼叫的值都儲存在其中。每次函式被呼叫,返回位址以及呼叫者的環境資訊(如某些暫存器)會被儲存在棧中。新呼叫函式會在棧中為其自動變數以及臨時變數分配記憶體。

這就是c中遞迴函式能工作的原因。每次乙個遞迴函式呼叫自己,乙個新的棧幀會被使用,這樣本地呼叫中的變數值不會干擾下一次的呼叫。

5. heap

堆通常用於動態記憶體管理。

堆開始於bss段末尾,並且往高位址增長。堆記憶體由malloc, realloc, 和free管理,可能會使用系統呼叫brk和sbrk來調整大小(注意,brk/sbrk和乙個單獨的堆區並不一定等價於malloc/realloc/free, 它們也可能使用mmap來預留虛擬記憶體的潛在非連續區域,加入到程序的虛擬位址空間中)。

在乙個程序中,堆區在所有的共享庫之間共享,並動態地載入模組。

以下所有例子都執行在環境: centos7.2 + gcc4.8.5

linux上的size(1)命令可以檢視text, data以及bss段的大小(位元組為單位)。

#include int main(void)

bash-4.1$ gcc memorylayout.c -o memorylayout

bash-4.1$ size memorylayout

text    data  bss  dec    hex    filename

1129  540   4     1673   689   memorylayout

#include int global; //未初始化資料段bss

int main(void)

bash-4.1$ gcc memorylayout.c -o memorylayout

bash-4.1$ size memorylayout

text    data   bss  dec      hex    filename

1229  548121789    6fd    memorylayout

bash-4.1$ ./memorylayout

&global=0x601038

由上可知,未初始化全域性變數,確實處於bss段中。

#include int global; //未初始化資料段bss

int main(void)

bash-4.1$ gcc memorylayout.c -o memorylayout

bash-4.1$ size memorylayout

text    data   bss  dec      hex    filename

1279  548    121839    72f    memorylayout

bash-4.1$ ./memorylayout

&global=0x60103c

&localstatic=0x601038

#include int global; //未初始化資料段bss

int main(void)

bash-4.1$ gcc memorylayout.c -o memorylayout

bash-4.1$ size memorylayout

text    data   bss  dec      hex    filename

1279  552

81839    72f    memorylayout

bash-4.1$ ./memorylayout

&global=0x60103c

&localstatic=0x601034

#include int global = 99; //初始化的全域性變數,儲存在資料段

int main(void)

bash-4.1$ gcc memorylayout.c -o memorylayout

bash-4.1$ size memorylayout

text    data   bss  dec      hex    filename

1279  556

41839    72f    memorylayout

bash-4.1$ ./memorylayout

&global=0x601034

&localstatic=0x601038

c程式的記憶體分布

一 c程式的記憶體分布 既然static是用來修飾變數和函式的,而變數和函式又是組成 c程式必不可少的,c程式的 記憶體分布圖如下。c 程式由下面5 部分組成 1 正文段 cpu 執行的機器指令部分 乙個程式只有乙個副本 唯讀,防止程式由於意外事故而修改自身指令 2 初始化資料段 資料段 在程式中所...

C程式記憶體分布

1 棧區 stack 由編譯器自動分配釋放,存放函式的引數值,區域性變數值等。2 堆區 heap 一般由程式設計師分配釋放,隨叫隨到,揮之即走。3 全域性 靜態區 static 全域性變數和靜態變數的儲存是放在一起的,在程式編譯時分配。4 文字常量區 存放常量字串。5 程式 區 存放函式體 包括類的...

C 程式記憶體分布

程式中變數的記憶體分配方式 程式執行時需要占用多大的空間需要在編譯時確定,便於作業系統為程式分配適當的記憶體空間。從靜態儲存區分配 程式的全域性變數和靜態變數都在這裡分配,且在編譯時已經分配好,在程式終止前被作業系統 在棧上建立 在函式呼叫時,函式的形參和區域性變數都在棧上建立,函式執行完畢時這些記...