BSS段:(bss segment)一般是指用來存放程序中未初始化的全局變量的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態內存分配。 程序員
例如: 數據結構
#include <stdio.h> 架構
int g1=0, g2=0, g3=0; 函數
int max(int i)
{
int m1=0,m2,m3=0,*p_max;
static n1_max=0,n2_max,n3_max=0;
p_max = (int*)malloc(10);
printf("打印max程序地址\n");
printf("in max: 0x%08x\n\n",max);
printf("打印max傳入參數地址\n");
printf("in max: 0x%08x\n\n",&i);
printf("打印max函數中靜態變量地址\n");
printf("0x%08x\n",&n1_max); //打印各本地變量的內存地址
printf("0x%08x\n",&n2_max);
printf("0x%08x\n\n",&n3_max);
printf("打印max函數中局部變量地址\n");
printf("0x%08x\n",&m1); //打印各本地變量的內存地址
printf("0x%08x\n",&m2);
printf("0x%08x\n\n",&m3);
printf("打印max函數中malloc分配地址\n");
printf("0x%08x\n\n",p_max); //打印各本地變量的內存地址 優化
if(i) return 1;
else return 0;
} spa
int main(int argc, char **argv)
{
static int s1=0, s2, s3=0;
int v1=0, v2, v3=0;
int *p;
p = (int*)malloc(10); 操作系統
printf("打印各全局變量(已初始化)的內存地址\n");
printf("0x%08x\n",&g1); //打印各全局變量的內存地址
printf("0x%08x\n",&g2);
printf("0x%08x\n\n",&g3);
printf("======================\n");
printf("打印程序初始程序main地址\n");
printf("main: 0x%08x\n\n", main);
printf("打印主參地址\n");
printf("argv: 0x%08x\n\n",argv);
printf("打印各靜態變量的內存地址\n");
printf("0x%08x\n",&s1); //打印各靜態變量的內存地址
printf("0x%08x\n",&s2);
printf("0x%08x\n\n",&s3);
printf("打印各局部變量的內存地址\n");
printf("0x%08x\n",&v1); //打印各本地變量的內存地址
printf("0x%08x\n",&v2);
printf("0x%08x\n\n",&v3);
printf("打印malloc分配的堆地址\n");
printf("malloc: 0x%08x\n\n",p);
printf("======================\n");
max(v1);
printf("======================\n");
printf("打印子函數起始地址\n");
printf("max: 0x%08x\n\n",max);
return 0;
} .net
打印結果: unix
能夠大體查看整個程序在內存中的分配狀況:
能夠看出,傳入的參數,局部變量,都是在棧頂分佈,隨着子函數的增多而向下增加.
函數的調用地址(函數運行代碼),全局變量,靜態變量都是在分配內存的低部存在,而malloc分配的堆則存在於這些內存之上,並向上生長. code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在操做系統中,一個進程就是處於執行期的程序(固然包括系統資源),實際上正在執行的程序代碼的活標本。那麼進程的邏輯地址空間是如何劃分的呢?
引用:
圖1作了簡單的說明(Linux系統下的)
左邊的是UNIX/LINUX系統的執行文件,右邊是對應進程邏輯地址空間的劃分狀況。
首先是堆棧區(stack),堆棧是由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操做方式相似於數據結構中的棧。棧的申請是由系統自動分配,如在函數內部申請一個局部變量 int h,同時判別所申請空間是否小於棧的剩餘空間,如若小於的話,在堆棧中爲其開闢空間,爲程序提供內存,不然將報異常提示棧溢出。
其次是堆(heap),堆通常由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式卻是相似於鏈表。堆的申請是由程序員本身來操做的,在C中使用malloc函數,而C++中使用new運算符,可是堆的申請過程比較複雜:當系統收到程序的申請時,會遍歷記錄空閒內存地址的鏈表,以求尋找第一個空間大於所申請空間的堆結點,而後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序,此處應該注意的是有些狀況下,新申請的內存塊的首地址記錄本次分配的內存塊大小,這樣在delete尤爲是delete[]時就能正確的釋放內存空間。
接着是全局數據區(靜態區) (static),全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另外一塊區域。 另外文字常量區,常量字符串就是放在這裏,程序結束後有系統釋放。
最後是程序代碼區,放着函數體的二進制代碼。
舉例說明一下:
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;
}