轉自
https://blog.csdn.net/qq_30943863/article/details/78254041
內容一
1. 棧(stack):又稱堆棧,棧是由編譯器自動分配釋放,存放函數的參數值,局部變量的值等(但不包括static聲明的變量,static意味着在數據段中存放變量)。除此之外,在函數被調用時,棧用來傳遞參數和返回值。由於棧的先進后出的特點,所以棧特別方便用來保存/恢復調用數據。其操作方式類似於數據結構中的棧。
2. 堆(heap):堆是用於存放進程運行中被動態分配的內存段,它的大小,並不固定,可動態擴張或縮放。當進程調用malloc/free等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張)/釋放的內存從堆中被提出(堆被縮減)。堆一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表。
3. 全局數據區(靜態區)(static):全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和靜態變量在相鄰的另一塊區域。另外文字常量區,常量字符串就是放在這里,程序結束后由系統釋放。
(1) BSS段(bss segment):通常是指用來存放程序中**未初始化**的全局變量的一塊內存區域。BSS段屬於靜態內存分配。
(2) 數據段(data segment):通常是指用來存放程序中**已初始化**的全局變量的一塊內存區域。數據段屬於靜態內存分配。
4. 代碼段(code segment/text segment):通常是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行之前就已經確定,並且內存區域通常屬於只讀,某些架構也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數變量,例如字符串常量等。程序段為程序代碼在內存中的映射,一個程序可以在內存中有多個副本。
C語言中內存分布
例如:
int a = 0; //全局初始化區
char *p1; //全局未初始化區
int main() {
int b; // 棧
char s[] = "abc"; //棧
char *p2; //棧
char *p3 = "123456"; //123456\0在常量區,而p3在棧上。
static int c =0; //全局(靜態)初始化區
p1 = (char *)malloc(10);
p2 = (char *)malloc(20); //分配得來得10和20字節的區域就在堆區。
strcpy(p1, "123456"); //123456\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。
return 0;
}
也有說法
1.由C語言代碼(文本文件)形成可執行程序(二進制文件),需要經過編譯-匯編-連接三個階段。編譯過程把C語言文本文件生成匯編程序,匯編過程把匯編程序形成二進制機器代碼,連接過程則將各個源文件生成的二進制機器代碼文件組合成一個文件。
2.C語言編寫的程序經過編譯-連接后,將形成一個統一文件,它由幾個部分組成。在程序運行時又會產生其他幾個部分,各個部分代表了不同的存儲區域:
1>代碼段(Code或Text)
代碼段由程序中執行的機器代碼組成。在C語言中,程序語句執行編譯后,形成機器代碼。在執行程序的過程中,CPU的程序計數器指向代碼段的每一條機器代碼,並由處理器依次運行。
2>只讀數據段(RO data)
只讀數據段是程序使用的一些不會被更改的數據,使用這些數據的方式類似查表式的操作,由於這些變量不需要更改,因此只需要放置在只讀存儲器中即可。
3>已初始化讀寫數據段(RW data)
已初始化數據是在程序中聲明,並且具有初值的變量,這些變量需要占用存儲器的空間,在程序執行時它們需要位於可讀寫的內存區域內,並且有初值,以供程序運行時讀寫。
4>未初始化數據段(BBS)
未初始化數據是在程序中聲明,但是沒有初始化的變量,這些變量在程序運行之前不需要占用存儲器的空間。
5>堆(heap)
堆內存只在程序運行時出現,一般由程序員分配和釋放。在具有操作系統的情況下,如果程序沒有釋放,操作系統可能在程序(例如一個進程)結束后會后內存。
6>棧(statck)
堆內存只在程序運行時出現,在函數內部使用的變量,函數的參數以及返回值將使用棧空間,棧空間由編譯器自動分配和釋放。
內容二:
C語言在編譯和連接后,將生成代碼段(Text)、只讀數據段(ROData)和讀寫數據段(RWData)。在運行時,除了以上三個區域外,還包括未初始化數據段(BSS)區域和堆(Heap)區域和棧(Stack)區域。
C語言程序的段
1、代碼段(code或text)
代碼段由各個函數產生,函數的每一個語句將最終經過編繹和匯編生成二進制機器代碼(具體生生哪種體系結構的機器代碼由編譯器決定)。
2、只讀數據段(ROData)
只讀數據段由程序中所使用的數據產生,該部分數據的特點是在運行中不需要改變,因此編譯器會將該數據段放入只讀的部分中。C語言中的只讀全局變量,只讀局部變量,程序中使用的常量等會在編譯時被放入到只讀數據區。 注意:定義全局變量constchara[100]={"ABCDEFG"};將生成大小為100個字節的只讀數據區,並使用“ABCDEFG”初始化。如果定義為:constchara[]={"ABCDEFG"};則根據字符串長度生成8個字節的只讀數據段(還有’\0’),所以在只讀數據段中,一般都需要做完全的初始化。
3、讀寫數據段(RWData)
讀寫數據段表示了在目標文件中一部分可以讀也可以寫的數據區,在某些場合它們又被稱為已初始化數據段,這部分數據段和代碼段,與只讀數據段一樣都屬於程序中的靜態區域,但具有可寫性的特點。通常已初始化的全局變量和局部靜態變量被放在了讀寫數據段,如:在函數中定義staticcharb[100]={“ABCDEFG”};讀寫數據區的特點是必須在程序經過初始化,如果只定義,沒初始值,則不會生成讀寫數據區,而會定位為未初始化數據區(BSS)。如果全局變量(函數外部定義的變量)加入static修飾,這表示只能在文件內使用,而不能被其他文件使用。
4、未初始化數據段(BSS)
與讀寫數據段類似,它也屬於靜態數據區,但是該段中的數據沒有經過初始化。因此它只會在目標文件中被標識,而不會真正稱為目標文件中的一段,該段將會在運行時產生。未初始化數據段只在運行的初始化階段才會產生,因此它的大小不會影響目標文件的大小。