Linux下C程式的儲存空間布局

2021-06-22 00:50:56 字數 2822 閱讀 2683

下面是對可執行檔案aa執行size命令後得到的結果。

[root@***1 algriom]# size aa

text      data    bss    dec    hex   filename

1257    500     16   1773    6ed  aa

其中:text:表示正文段大小,這是cpu執行的機器指令部分,通常,正文段是可共享的,所以即使是頻繁執行的程式在儲存器中也只需有乙個副本;

data:表示包含靜態變數和已經初始化(可執行檔案包含了初始化的值)的全域性變數的資料段大小;

bss :表示由可執行檔案中不含其初始化值的全域性變數組成,稱之為未初始化資料段;

ps:第4列和第5列是分別以十進位制和十六進製制表示的三個段的總長度。

bss段:bss段(bss segment)通常是指用來存放程式中未初始化的全域性變數的一塊記憶體區域。bss的英文是block started by symbol的簡稱。bss段屬於靜態記憶體分配。

資料段:資料段(data segment)通過是指用來存放程式已經初始化的全域性變數的一塊記憶體區域。資料段屬於靜態記憶體分配。

**段:**段(code segment/text segment)通常是指用來存放程式執行**的一塊記憶體區域。這部分區域的大小在程式執行前就已經確定,並且記憶體區域通常屬於唯讀,某些架構也允許**段為可寫,即允許修改程式。在**段中,也有可能包含一些唯讀的常數變數,比如字串常量等。

堆:堆(heap)是用於存放程序執行中動態分配的記憶體段,它的大小並不固定,可動態擴張或縮減。當程序呼叫malloc等函式分配記憶體的時候,新分配的記憶體就被動態新增到堆上(堆被擴張);當利用free等函式釋放記憶體的時候,被釋放的記憶體從堆中被剔除(堆被縮減)。

棧:棧(stack)又稱堆疊,是使用者存放程式臨時建立的區域性變數,也就是我們函式括弧{}中定義的比變數(但不包括static宣告的靜態變數,static意味著在資料段中存放的變數)。除此之外,在函式被呼叫時,其引數也會被壓入發起呼叫的程序棧中,並且等到呼叫結束後,函式的返回值也會被存放回棧中。由於棧先進後出的特點,所以棧特別方便用來儲存/恢復呼叫現場。從這個意義上講,我們可以把堆疊看成乙個寄存、交換臨時資料的記憶體區。

[root@***1 algriom]# size aa

text   data    bss    dec    hex filename

1257    500     16   1773    6ed aa

可以看到乙個可執行程式在儲存(沒有調入記憶體)時分為**段、資料區和未初始化資料區三部分。

(1)**區:也稱之為正文段,這是存放cpu執行的機器指令。通常**區是共享的,即其它執行程式可以呼叫它。**段(code segment/text segment)通常是唯讀的,有些架構也允許自行修改。

(2)資料區:存放已經初始化的全域性變數、已經初始化的靜態變數(包括全域性和區域性的)。

(3)未初始化資料區(block started by symbol,bss)存放未初始化的全域性變數和未初始化的靜態變數。bss的資料在程式開始執行之前被初始化為0或null。

**區所在的位址空間最低,往上依次是資料區和bss區,並且資料區和bss區在記憶體中是緊挨著的。

典型的儲存器安排,入下圖所示。

text段和data段在編譯時已經分配了空間,而bss段並不占用可執行檔案的大小,它是由鏈結器來獲取記憶體的。

bss段(未進行初始化的資料)的內容並不存放在磁碟上的程式檔案中。其原因是核心在程式開始執行前將它們設定為0。需要存放在程式檔案中的只有正文段和初始化資料段。

data段(已經初始化的資料)則為資料分配空間,資料儲存到目標檔案中。

資料段包含經過初始化的全域性變數以及它們的值。bss段的大小從可執行檔案中得到,然後鏈結器得到這個大小的記憶體塊,緊跟在資料段的後面。當這個記憶體進入程式的位址空間後全部清零。包含資料段和bss段的整個區段此時通常稱為資料區。

可執行程式在執行時又多出兩個區域:棧區和堆區。

(4)棧區:由編譯器自動釋放,存放函式的引數值、區域性變數等。每當乙個函式被呼叫時,該函式的返回型別和一些呼叫的資訊被存放到棧中。然後這個被呼叫的函式再為他的自動變數和臨時變數在棧上分配空間。每呼叫乙個函式乙個新的棧就會被使用。棧區是從高位址位向低位址位增長的,是一塊連續的記憶體區域,最大容量是由系統預先定義好的,申請的棧空間超過這個界限時會提示溢位,使用者能從棧中獲取的空間較小。

(5)堆區:用於動態分配記憶體,位於bss和棧中間的位址區域。由程式設計師申請分配和釋放。堆是從低位址位向高位址位增長,採用鏈式儲存結構。頻繁的malloc/free造成記憶體空間的不連續,產生碎片。當申請堆空間時庫函式是按照一定的演算法搜尋可用的足夠大的空間。因此堆的效率比棧要低的多。

注意:a.out中還有若干其他型別的段,例如,包含符號表的段、包含除錯資訊的段以及包含動態共享庫鏈結表的段等等。這些部分並不裝載到程序執行的程式映像中。

舉個例子說明各種變數存在什麼區:

int a=0;

//a在全域性已初始化資料區 

char *p1;

//p1在bss區(未初始化全域性變數) 

main()

結論:1

、經過初始化的全域性變數和靜態變數儲存在資料段中。2、

未經初始化的全域性變數和靜態變數儲存在

bss段。3、

函式內部宣告的區域性變數儲存在堆疊段中。4、

const

修飾的全域性變數儲存在文字段中,

const

修飾的區域性變數儲存在堆疊段中。5、

字串常量儲存在文字段中。

Linux下C程式的儲存空間布局

下面是對可執行檔案aa執行size命令後得到的結果。root 1 algriom size aa text data bss dec hex filename 1257 500 16 1773 6ed aa 其中 text 表示正文段大小,這是cpu執行的機器指令部分,通常,正文段是可共享的,所以即...

Linux下C程式的儲存空間布局

在elf格式的可執行檔案中,全域性記憶體包括三種 bss data和rodata。其它可執行檔案格式與之類似。了解了這三種資料的特點,我們才能充分發揮它們的長處,達到速度與空間的最優化。1 bss block started by symbol bss是指那些沒有初始化的和初始化為0的全域性變數和靜...

Linux下C程式的儲存空間布局

乙個程式本質上都是由 bss 段 data段 text段三個組成的。可以看到乙個可執行程式在儲存 沒有調入記憶體 時分為 段 資料區和未初始化資料區三部分。程式編譯後生成的目標檔案至少含有這三個段,這三個段的大致結構圖如下所示 text段和data段在編譯時已經分配了空間,而bss段並不占用可執行檔...