C/C++內存分配與Linux內存管理進程所涉及到的五個數據段

一. 在c中分爲這幾個存儲區
1.棧 - 由編譯器自動分配釋放
2.堆 - 一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收
3.全局區(靜態區),全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。- 程序結束釋放
4.另外還有一個專門放常量的地方。- 程序結束釋放
                                                                                                                                             
在函數體中定義的變量通常是在棧上,用malloc, calloc, realloc等分配內存的函數分配得到的就是在堆上。在所有函數體外定義的是全局量,加了static修飾符後不管在哪裏都存放在全局區(靜態區),在所有函數體外定義的static變量表示在該文件中有效,不能extern到別的文件用,在函數體內定義的static表示只在該函數體內有效。另外,函數中的"adgfdf"這樣的字符串存放在常量區。比如:
int a = 0; //全局初始化區
char *p1; //全局未初始化區
void main()
{
    int b; //棧
    char s[] = "abc"; //棧
    char *p2; //棧
    char *p3 = "123456"; //123456{post.content}在常量區,p3在棧上
    static int c = 0; //全局(靜態)初始化區
    p1 = (char *)malloc(10); //分配得來得10字節的區域在堆區
    p2 = (char *)malloc(20); //分配得來得20字節的區域在堆區
    strcpy(p1, "123456");
    //123456{post.content}放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一塊
}

二.在C++中,內存分成5個區,他們分別是堆、棧、自由存儲區、全局/靜態存儲區和常量存儲區
1.棧,就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變量的存儲區。裏面的變量通常是局部變量、函數參數等。
2.堆,就是那些由new分配的內存塊,他們的釋放編譯器不去管,由我們的應用程序去控制,一般一個new就要對應一個delete。如果程序員沒有釋放掉,那麼在程序結束後,操作系統會自動回收。
3.自由存儲區,就是那些由malloc等分配的內存塊,他和堆是十分相似的,不過它是用free來結束自己的生命的。
4.全局/靜態存儲區,全局變量和靜態變量被分配到同一塊內存中,在以前的C語言中,全局變量又分爲初始化的和未初始化的,在C++裏面沒有這個區分了,他們共同佔用同一塊內存區。
5.常量存儲區,這是一塊比較特殊的存儲區,他們裏面存放的是常量,不允許修改(當然,你要通過非正當手段也可以修改)

 

Linux內存管理進程所涉及到的五個數據段

進 程(執行的程序)會佔用一定數量的內存,它或是用來存放從磁盤載入的程序代碼,或是存放取自用戶輸入的數據等等。不過進程對這些內存的管理方式因內存用途 不一而不盡相同,有些內存是事先靜態分配和統一回收的,而有些卻是按需要動態分配和回收的。對任何一個普通進程來講,它都會涉及到5種不同的數據段。

一、Linux進程的五個段

下面我們來簡單歸納一下進程對應的內存空間中所包含的5種不同的數據區都是幹什麼的。

1)代碼段:代碼段是用來存放可執行文件的操作指令,也就是說是它是可執行程序在內存中的鏡像。代碼段需要防止在運行時被非法修改,所以只准許讀取操作,而不允許寫入(修改)操作——它是不可寫的。

2)數據段:數據段用來存放可執行文件中已初始化全局變量,換句話說就是存放程序靜態分配的變量和全局變量。

3)BSS段:BSS段包含了程序中未初始化的全局變量,在內存中 bss段全部置零。

4)堆(heap):堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)

  它的物理內存空間是由程序申請的,並由程序負責釋放。

5)棧:棧是用戶存放程序臨時創建的局部變量,也就是說我們函數括弧“{}”中定義的變量(但不包括static聲明的變量,static意味着在數據段中存放變量)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,並且待到調用結束後,函數的返回值也會被存放回棧中。由於棧的先進先出特點,所以棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的內存區。

   它是由操作系統分配的,內存的申請與回收都由OS管理。

舉個具體的C語言的例子吧:

//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字節的區域就在堆區。

}

二、各個段在內存中的組織

各個段段在線性空間中的組織。直接上圖:

+--------------------------------   高地址

+ envstrings 環境變量字串    

+--------------------------------

+ argv string 命令行字串        

+--------------------------------

 
+ env pointers 環境變量指針表

+--------------------------------

+ argv pointers命令行參數指針表

+--------------------------------

+ argc 命令行參數個數 

+--------------------------------

 
+     main函數的棧幀  

+--------------------------------

+     被調用函數的棧幀

+--------------------------------

+         ......                

+--------------------------------

 

 
+       堆(heap)                

+--------------------------------

 

 
+   BSS 未初始化全局數據     

+--------------------------------

 

 
+   Data 初始化的全局數據    

+--------------------------------

 
+   Text  代碼段                

+--------------------------------   

 

其中,Heap,BSS,Data這三個段在物理內存中是連續存放的,可以這麼理解:這三個是一體的。Text、Stack是獨立存放的,這是現在Linux中個段的分佈,在0.11中代碼段和數據段不是分立的,是在一起的也就是說數據段和代碼段是一個段,當然了,堆與BSS也與它們一起了。從0.11的task_struct中還可以看出數據段、堆棧段的描述符是一個,都在ldt[2]處。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章