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


一個程序本質上都是由 BSS 段、data段、text段三個組成的。可以看到一個可執行程序在存儲(沒有調入內存)時分為代碼段、數據區和未初始化數據區三部分。

  • BSS段(未初始化數據區):在采用段式內存管理的架構中,BSS段(bss segment)通常是指用來存放程序中未初始化的全局變量的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態內存分配。
  • 數據段:在采用段式內存管理的架構中,數據段(data segment)通常是指用來存放程序中已初始化的全局變量的一塊內存區域。數據段屬於靜態內存分配。
  • 代碼段:在采用段式內存管理的架構中,代碼段(text segment)通常是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經確定,並且內存區域屬於只讀。在代碼段中,也有可能包含一些只讀的常數變量,例如字符串常量等。

程序編譯后生成的目標文件至少含有這三個段,這三個段的大致結構圖如下所示:

text段和data段在編譯時已經分配了空間,而BSS段並不占用可執行文件的大小,它是由鏈接器來獲取內存的
    bss段(未進行初始化的數據)的內容並不存放在磁盤上的程序文件中。其原因是內核在程序開始運行前將它們設置為0。需要存放在程序文件中的只有正文段和初始化數據段。
    data段(已經初始化的數據)則為數據分配空間,數據保存到目標文件中。

數據段包含經過初始化的全局變量以及它們的值。BSS段的大小從可執行文件中得到,然后鏈接器得到這個大小的內存塊,緊跟在數據段的后面。當這個內存進入程序的地址空間后全部清零。包含數據段和BSS段的整個區段此時通常稱為數據區。

    可執行程序在運行時又多出兩個區域:棧區和堆區。
    (4)棧區:由編譯器自動釋放,存放函數的參數值、局部變量等。每當一個函數被調用時,該函數的返回類型和一些調用的信息被存放到棧中。然后這個被調用的 函數再為他的自動變量和臨時變量在棧上分配空間。每調用一個函數一個新的棧就會被使用。棧區是從高地址位向低地址位增長的,是一塊連續的內存區域,最大容 量是由系統預先定義好的,申請的棧空間超過這個界限時會提示溢出,用戶能從棧中獲取的空間較小。
    (5)堆區:用於動態分配內存,位於BSS和棧中間的地址區域。由程序員申請分配和釋放。堆是從低地址位向高地址位增長,采用鏈式存儲結構。頻繁的 malloc/free造成內存空間的不連續,產生碎片。當申請堆空間時庫函數是按照一定的算法搜索可用的足夠大的空間。因此堆的效率比棧要低的多。

下圖將體現c的源文件對應存儲空間:

此時程序還沒有被放入內存,只是在硬盤存儲的情況,此時bss並未占用空間。bss在鏈接的時候被獲得內存空間。

下圖表示程序運行,即程序在內存時的存儲布局:

 

 

 

//main.c  
int a = 0; //全局初始化區  
char *p1; //全局未初始化區  
  
main()  
{  
    static int c =0//全局(靜態)初始化區  
    int b; //
    char s[] = "abc"; //
    char *p2; //
    char *p3 = "123456"; //"123456\0"在常量區,p3在棧上。  
    p1 = (char *)malloc(10);  
    p2 = (char *)malloc(20); //分配得來得10和20字節的區域就在堆區。  
}

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM