一般情況下,一個可執行二進位程式(更確切的說,在Linux作業系統下為一個進程單元,在UC/OSII中被稱為任務)在儲存(沒有調入到記憶體運行)時擁有3個部分,分別是程式碼片段(text)、資料區段(data)和BSS段。這3個部分一起組成了該可執行程式的檔案
C語言可執行代碼結構
名稱 |
內容 |
程式碼片段 |
可執行代碼、字串常量 |
資料區段 |
已初始化全域變數、已初始化全域靜態變數、局部靜態變數、常量資料 |
BSS段 |
未初始化全域變數,未初始化全域靜態變數 |
棧 |
局部變數、函數參數 |
堆 |
動態記憶體分配 |
(1)程式碼片段(text segment):存放CPU執行的機器指令。通常程式碼片段是可共用的,這使得需要頻繁被執行的程式只需要在記憶體中擁有一份拷貝即可。程式碼片段也通常是唯讀,這樣可以防止其他程式意外地修改其指令。另外,程式碼片段還規划了局部資料所申請的記憶體空間資訊。
代 碼段(code segment/text segment)通常是指用來存放程式執行代碼的一塊記憶體地區。這部分地區的大小在程式運行前就已經確定,並且記憶體地區通常屬於唯讀, 某些架構也允許程式碼片段為可寫,即允許修改程式。在程式碼片段中,也有可能包含一些唯讀常數變數,例如字串常量等。
(2)資料區段(data segment):或稱全域初始化資料區段/待用資料段(initialized data segment/data segment)。該段包含了在程式中明確被初始化的全域變數、靜態變數(包括全域靜態變數和局部靜態變數)和常量資料。
(3)未初始化資料區段:亦稱BSS(Block Started by Symbol)。該段存入的是全域未初始設定變數、靜態未初始設定變數。
而當程式被載入到記憶體單元時,則需要另外兩個域:堆域和棧域。
(4)棧段(stack):存放函數的參數值、局部變數的值,以及在進行任務切換時存放當前任務的上下文內容。
(5)堆段(heap):用於動態記憶體分配,即使用malloc/free系列函數來管理的記憶體空間。
在將應用程式載入到記憶體空間執行時,作業系統負責程式碼片段、資料區段和BSS段的載入,並將在記憶體中為這些段分配空間。棧段亦由作業系統分配和管理,而不需要程式員顯示地管理;堆段由程式員自己管理,即顯示地申請和釋放空間。
另外,可執行程式在運行時具有相應的程式屬性。在有作業系統支援時,這些屬性頁面由作業系統管理和維護。
下面給出樣本程式碼,注釋已經在代碼中寫明:
複製代碼 代碼如下:
/*程式碼片段、資料區段和BSS段儲存變數類型*/
#include <stdio.h>
const int g_A = 10; //程式碼片段
int g_B = 20; //資料區段
static int g_C = 30; //資料區段
static int g_D; //BSS段
int g_E; //BSS段
char *p1; //BSS段
void main( )
{
int local_A; //棧
static int local_C = 0; //資料區段
static int local_D; //資料區段
char *p3 = "123456"; //123456在程式碼片段,p3在棧上
p1 = (char *)malloc( 10 ); //堆,分配得來得10位元組的地區在堆區
strcpy( p1, "123456" ); //123456{post.content}放在常量區,編譯器可能會將它與p3所指向 的"123456"最佳化成一塊
printf("n");
printf( "程式碼片段,全域初始設定變數, 唯讀const, g_A, addr:0x%08xn", &g_A);
printf("n");
printf( "資料區段,全域變數, 初始化 g_B, addr:0x%08xn", &g_B);
printf( "資料區段,靜態全域變數, 初始化, g_C, addr:0x%08xn", &g_C);
printf("n");
printf( "BSS段, 全域變數, 未初始化 g_E, addr:0x%08xn", &g_E, g_E );
printf( "BSS段, 靜態全域變數, 未初始化, g_D, addr:0x%08xn", &g_D );
printf( "BSS段, 靜態局部變數, 初始化, local_C, addr:0x%08xn", &local_C);
printf( "BSS段, 靜態局部變數, 未初始化, local_D, addr:0x%08xn", &local_D);
printf("n");
printf( "棧, 局部變數, local_A, addr:0x%08xn", &local_A );
printf("n");
printf( "堆, malloc分配記憶體, p1, addr:0x%08xn", p1 );
}