在標準C語言中,編譯出來的可執(zhí)行程序分為代碼區(qū)(text)、數(shù)據(jù)區(qū)(data)和未初始化數(shù)據(jù)區(qū)(bss)3個部分。如下代碼
#include
int a = 0; //a在全局已初始化數(shù)據(jù)區(qū)
char *p1; //p1在BSS區(qū)(未初始化全局變量)
void main()
{
int b; //b在棧區(qū)
int c; //C為全局(靜態(tài))數(shù)據(jù),存在于已初始化數(shù)據(jù)區(qū)
char s[] = "abc"; //s為數(shù)組變量,存儲在棧區(qū),
char *p2,*p3; //p2、p3在棧區(qū)
p2 = (char *)malloc(10);//分配得來的10個字節(jié)的區(qū)域在堆區(qū)
p3 = (char *)malloc(20);//分配得來的20個字節(jié)的區(qū)域在堆區(qū)
free(p2);
free(p3);
}
使用linux編譯之后得到的可執(zhí)行文件如下
?可以看到代碼區(qū)(text)、數(shù)據(jù)區(qū)(data)和未初始化數(shù)據(jù)區(qū)(bss)。
代碼段(text):存放代碼的地方。只能訪問,不能修改,代碼段就是程序中的可執(zhí)行部分,直觀理解代碼段就是函數(shù)堆疊組成的。
數(shù)據(jù)段(data):全局變量和靜態(tài)局部變量存放的地方。也被稱為數(shù)據(jù)區(qū)、靜態(tài)數(shù)據(jù)區(qū)、靜態(tài)區(qū):數(shù)據(jù)段就是程序中的數(shù)據(jù),直觀理解就是C語言程序中的全局變量。注意是全局變量或靜態(tài)局部變量,局部變量不算。
未初始化數(shù)據(jù)區(qū)(bss):bss段的特點就是被初始化為0,bss段本質(zhì)上也是屬于數(shù)據(jù)段。
那么問題來了,為什么要區(qū)分data段和bss段呢?
以下面代碼為例,a.c和b.c的差異只是有沒有給arr數(shù)組賦值。
?可以看到a.out的bss段大,b.out的data段大。但是b.out的文件大小明顯比a.out的大很多。data段會增大可執(zhí)行文件的大小,而bss段不會。
data段是全局變量,但是需要初始化值,上面我的例子是全部初始全部為1,但也可能是1024*1024個不同的數(shù)據(jù),而這些數(shù)據(jù)需要保存起來,表現(xiàn)出來也就是需要保存在可執(zhí)行文件中。
bss段也是全局變量,但不需要初始化值,只需要保存一下這個全部變量的保存的數(shù)據(jù)類型和大小即可。即使它的數(shù)組容量是1024*1024,也不會占用很多可執(zhí)行文件的大小。
如果一個全部變量初始化為0,那么它也是bss段,不是data段,即使你代碼中把它初始化為0了。
關(guān)于數(shù)據(jù)段,也就是data段,也會分為RO data(只讀數(shù)據(jù)段)和RW data(讀寫數(shù)據(jù)段)。
- 只讀數(shù)據(jù)段:程序使用的一些不會被更改的數(shù)據(jù),使用這些數(shù)據(jù)的方式類似查表式的操作,由于這些變量不需要更改,因此只需要放置在只讀存儲器中即可。
- 讀寫數(shù)據(jù)段:程序中是可以被更改的數(shù)據(jù),且初始化過的,所以需要放置在RAM中,且初始化的內(nèi)容放在存儲器中(表現(xiàn)為放入可執(zhí)行文件中)。
?上面說到“編譯出來的可執(zhí)行程序分為代碼區(qū)(text)、數(shù)據(jù)區(qū)(data)和未初始化數(shù)據(jù)區(qū)(bss)3個部分”,那運行中就會多出來一些區(qū)域,這就是我們常說的堆棧,注意堆棧是兩個區(qū)域堆和棧。
棧:局部變量、函數(shù)一般在棧空間中。運行時自動分配&自動回收:棧是自動管理的,程序員不需要手工干預(yù)。方便簡單。是提前分配好的連續(xù)的地址空間。棧的增長方向是向下的,即向著內(nèi)存地址減小的方向。
堆:堆內(nèi)存管理者總量很大的操作系統(tǒng)內(nèi)存塊,各進程可以按需申請使用,使用完釋放。程序手動申請&釋放:手工意思是需要寫代碼去申請malloc和釋放free??梢允遣贿B續(xù)的地址空間。堆的增長方向是向上的,即向著內(nèi)存地址增加的方向。
?下面是簡單的演示代碼
#include
#include
int bss_var; //未初始化全局數(shù)據(jù)存儲在BSS區(qū)
int data_var=42; //初始化全局數(shù)據(jù)存儲在數(shù)據(jù)區(qū)
int main(int argc,char *argv[])
{
char *p ,*b;
printf("Adr bss_var:0x%x\n",&bss_var);
printf("Adr data_var:0x%x\n",&data_var);
printf("the %s is at adr:0x%x\n","main",&main);
p=(char *)alloca(32); //從棧中分配空間
if(p!=NULL)
{
printf("the p start is at adr:0x%x\n",p);
printf("the p end is at adr:0x%x\n",p+31);
}
b=(char *)malloc(32*sizeof(char)); //從堆中分配空間
if(b!=NULL)
{
printf("the b start is at adr:0x%x\n",b);
printf("the b end is at adr:0x%x\n",b+31);
}
free(b); //釋放申請的空間,以避免內(nèi)存泄漏
while(1);
}
審核編輯:湯梓紅
-
C語言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136839 -
程序
+關(guān)注
關(guān)注
117文章
3787瀏覽量
81049 -
代碼
+關(guān)注
關(guān)注
30文章
4788瀏覽量
68616 -
內(nèi)存分配
+關(guān)注
關(guān)注
0文章
16瀏覽量
8307
發(fā)布評論請先 登錄
相關(guān)推薦
評論