www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號精選 > 嵌入式基地

程序運行時的內(nèi)存分區(qū)主要分為BSS段、數(shù)據(jù)段、代碼段、堆、棧。

  • BSS段:Block Started by Symbol,一般是指存放程序中未初始化的全局變量的一塊內(nèi)存區(qū)域。BSS段屬于靜態(tài)內(nèi)存分配。


  • 數(shù)據(jù)段:data segment,一般是指用來存放程序中已初始化的全局變量的一塊內(nèi)存區(qū)域。數(shù)據(jù)段屬于靜態(tài)內(nèi)存分配。


  • 代碼段:code segment/text segment,通常是指用來存放程序執(zhí)行代碼的一塊內(nèi)存區(qū)域。這部分區(qū)域的大小在程序運行前就已經(jīng)確定,并且內(nèi)存區(qū)域通常屬于只讀,某些架構(gòu)也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些 只讀的常數(shù)變量 ,例如字符串常量等。程序段為程序代碼在內(nèi)存中的映射。一個程序可以在內(nèi)存中有多個副本。


  • 堆:heap,堆是用于存放進程運行中被動態(tài)分配的內(nèi)存段,它的大小并不固定,可動態(tài)擴張或縮減。當(dāng)進程調(diào)用malloc/free等函數(shù)分配內(nèi)存時,新分配的內(nèi)存就被動態(tài)添加到堆上(堆被擴張)/釋放的內(nèi)存從堆中被剔除(堆被縮減)。


  • 棧:stack,棧又稱堆棧,存放程序的局部變量(但不包括static聲明的變量, static 意味著 在數(shù)據(jù)段中 存放變量)。除此以外,在函數(shù)被調(diào)用時,棧用來傳遞參數(shù)和返回值。由于棧的先進先出特點,所以棧特別方便用來保存/恢復(fù)調(diào)用現(xiàn)場。儲動態(tài)內(nèi)存分配,需要程序員手工分配,手工釋放。


程序中內(nèi)存分布圖

APUE中的C內(nèi)存分布圖

代碼測試


int g1=0, g2=0, g3=0; static 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: 0xx\n\n",max); printf("打印max傳入?yún)?shù)地址\n"); printf("in max: 0xx\n\n",&i); printf("打印max函數(shù)中靜態(tài)變量地址\n"); printf("0xx\n",&n1_max); ////< 打印各本地變量的內(nèi)存地址 printf("0xx\n",&n2_max); printf("0xx\n\n",&n3_max); printf("打印max函數(shù)中局部變量地址\n"); printf("0xx\n",&m1); ////< 打印各本地變量的內(nèi)存地址 printf("0xx\n",&m2); printf("0xx\n\n",&m3); printf("打印max函數(shù)中malloc分配地址\n"); printf("0xx\n\n",p_max); ////< 打印各本地變量的內(nèi)存地址 if(i) { return 1;
 } else { return 0;
 }
} 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èi)存地址\n"); printf("0xx\n",&g1); ////< 打印各全局變量的內(nèi)存地址 printf("0xx\n",&g2); printf("0xx\n\n",&g3); printf("======================\n"); printf("打印程序初始程序main地址\n"); printf("main: 0xx\n\n", main); printf("打印主參地址\n"); printf("argv: 0xx\n\n",argv); printf("打印各靜態(tài)變量的內(nèi)存地址\n"); printf("0xx\n",&s1); ////< 打印各靜態(tài)變量的內(nèi)存地址 printf("0xx\n",&s2); printf("0xx\n\n",&s3); printf("打印各局部變量的內(nèi)存地址\n"); printf("0xx\n",&v1); ////< 打印各本地變量的內(nèi)存地址 printf("0xx\n",&v2); printf("0xx\n\n",&v3); printf("打印malloc分配的堆地址\n"); printf("malloc: 0xx\n\n",p); printf("======================\n");
 max(v1); printf("======================\n"); printf("打印子函數(shù)起始地址\n"); printf("max: 0xx\n\n",max); return 0;
}

控制臺輸出結(jié)果

根據(jù)輸出結(jié)果可以看出,傳入的參數(shù),局部變量,都是在棧頂分布,隨著子函數(shù)的增多而向下增長。函數(shù)的調(diào)用地址(函數(shù)運行代碼),全局變量,靜態(tài)變量都是在分配內(nèi)存的低部存在,而malloc分配的堆則存在于這些內(nèi)存之上,并向上生長。


簡單說明

左邊的是UNIX/LINUX系統(tǒng)的執(zhí)行文件,右邊是對應(yīng)進程邏輯地址空間的劃分情況。


首先是堆棧區(qū)(stack),堆棧是由編譯器自動分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。棧的申請是由系統(tǒng)自動分配,如在函數(shù)內(nèi)部申請一個局部變量 int h,同時判別所申請空間是否小于棧的剩余空間,如若小于的話,在堆棧中為其開辟空間,為程序提供內(nèi)存,否則將報異常提示棧溢出。


其次是堆(heap),堆一般由程序員分配釋放,若程序員不釋放,程序結(jié)束時可能由OS回收。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,分配方式倒是類似于鏈表。堆的申請是由程序員自己來操作的,在C中使用malloc函數(shù),而C++中使用new運算符,但是堆的申請過程比較復(fù)雜:當(dāng)系統(tǒng)收到程序的申請時,會遍歷記錄空閑內(nèi)存地址的鏈表,以求尋找第一個空間大于所申請空間的堆結(jié)點,然后將該結(jié)點從空閑結(jié)點鏈表中刪除,并將該結(jié)點的空間分配給程序,此處應(yīng)該注意的是有些情況下,新申請的內(nèi)存塊的首地址記錄本次分配的內(nèi)存塊大小,這樣在delete尤其是 delete[]時就能正確的釋放內(nèi)存空間。


接著是全局?jǐn)?shù)據(jù)區(qū)(靜態(tài)區(qū)) (static),全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。另外文字常量區(qū),常量字符串就是放在這里,程序結(jié)束后有系統(tǒng)釋放。


最后是程序代碼區(qū),放著函數(shù)體的二進制代碼。


內(nèi)存分布對應(yīng)關(guān)系

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉