內(nèi)存

1. 結(jié)構(gòu)體字節(jié)對齊


struct S1{
    char c1;
    char c2;
    int n;
};
struct S2{
    char c1;
    int n;
    char c2;
};

printf("sizeof(struct S1) = %ld\n",sizeof(struct S1));
printf("sizeof(struct S2) = %ld\n",sizeof(struct S2));

在C語言里述召,結(jié)構(gòu)體所占的內(nèi)存是連續(xù)的,但是各個成員之間的地址不一定是連續(xù)的。所以就出現(xiàn)了"字節(jié)對齊"。

字節(jié)對齊默認原則

結(jié)構(gòu)體變量的大小顾瞻,一定是其最大的數(shù)據(jù)類型的大小的整數(shù)倍幔烛,如果某個數(shù)據(jù)類型大小不夠诚隙,就填充字節(jié)业舍。
結(jié)構(gòu)體變量的地址,一定和其第一個成員的地址是相同的鞍帝。

2.執(zhí)行下面代碼诫睬,分析代碼中各種變量的地址特點。

#include <stdio.h>
#include <stdlib.h>

void f1(){
  int f1local1;
  int f1local2;
  static int f1static1;
  static int f1static2;
  int* f1dynamic1 = malloc(sizeof(int));
  int* f1dynamic2 = malloc(sizeof(int));
  printf("--------------f1()----------------\n");
  printf("&f1local1   = %p\n",&f1local1);
  printf("&f1local2   = %p\n",&f1local2);
  printf("&f1static1  = %p\n",&f1static1);
  printf("&f1static2  = %p\n",&f1static2);
  printf("f1dynamic1  = %p\n",f1dynamic1);
  printf("f1dynamic2  = %p\n",f1dynamic2);
  printf("\"f1string1\" = %p\n","f1string1");
  printf("\"f1string2\" = %p\n","f1string2");
  printf("--------------f1()----------------\n");
  free(f1dynamic1);
  free(f1dynamic2);
}
void f2(){
  int f2local1;
  int f2local2;
  static int f2static1;
  static int f2static2;
  int* f2dynamic1 = malloc(sizeof(int));
  int* f2dynamic2 = malloc(sizeof(int));
  printf("--------------f2()----------------\n");
  printf("&f2local1   = %p\n",&f2local1);
  printf("&f2local2   = %p\n",&f2local2);
  printf("&f2static1  = %p\n",&f2static1);
  printf("&f2static2  = %p\n",&f2static2);
  printf("f2dynamic1  = %p\n",f2dynamic1);
  printf("f2dynamic2  = %p\n",f2dynamic2);
  printf("\"f2string1\" = %p\n","f2string1");
  printf("\"f2string2\" = %p\n","f2string2");
  printf("--------------f2()----------------\n");
  free(f2dynamic1);
  free(f2dynamic2);
}

int static1;
int static2;
int main(){
  int local1;
  int local2;
  int* dynamic1 = malloc(sizeof(int));
  int* dynamic2 = malloc(sizeof(int));
  printf("&local1   = %p\n",&local1);
  printf("&local2   = %p\n",&local2);
  printf("&static1  = %p\n",&static1);
  printf("&static2  = %p\n",&static2);
  printf("dynamic1  = %p\n",dynamic1);
  printf("dynamic2  = %p\n",dynamic2);
  printf("\"string1\" = %p\n","string1");
  printf("\"string2\" = %p\n","string2");
  printf("&f1 = %p\n",&f1);
  printf("&f2 = %p\n",&f2);
  f1();
  f2();
}

分析執(zhí)行結(jié)果

&local1   = 0x7ffc8b8120fc
&local2   = 0x7ffc8b8120f8
&static1  = 0x601060
&static2  = 0x601064
dynamic1  = 0x1d10010
dynamic2  = 0x1d10030
"string1" = 0x400b8f
"string2" = 0x400ba7
&f1 = 0x40060d
&f2 = 0x400707
--------------f1()----------------
&f1local1   = 0x7ffc8b8120cc
&f1local2   = 0x7ffc8b8120c8
&f1static1  = 0x601050
&f1static2  = 0x601054
f1dynamic1  = 0x1d10050
f1dynamic2  = 0x1d10070
"f1string1" = 0x400a2f
"f1string2" = 0x400a4b
--------------f1()----------------
--------------f2()----------------
&f2local1   = 0x7ffc8b8120cc
&f2local2   = 0x7ffc8b8120c8
&f2static1  = 0x601058
&f2static2  = 0x60105c
f2dynamic1  = 0x1d10070
f2dynamic2  = 0x1d10050
"f2string1" = 0x400af7
"f2string2" = 0x400b13
--------------f2()----------------

上面結(jié)果每次執(zhí)行結(jié)果會有所變化帕涌,不同計算機結(jié)果也會不同摄凡。但是會有如下規(guī)律:

1.局部變量、靜態(tài)變量蚓曼、動態(tài)分配內(nèi)存亲澡、字符串常量與函數(shù)分別放在一起,即使在不同的函數(shù)中纫版。
變量的存放地址大小有如下特點:

2.字符串常量與代碼 < 靜態(tài)變量 < 動態(tài)分配內(nèi)存 < 局部變量

3.靜態(tài)變量床绪、動態(tài)分配內(nèi)存、字符串常量與函數(shù)的相鄰變量地址是遞增的。局部變量相鄰變量地址是遞減的癞己。
4.字符串常量與函數(shù)是在一起的裹匙。

上面說明代碼在內(nèi)存中是按類型存放在不同的區(qū)里面的。

gcc -S test.c
gcc --save-temp test.c
readelf -S ./a.out
1730134-c16eb70c42a39508.png

2.1 棧區(qū)(stack)

由編譯器自動分配和釋放末秃,主要是存放函數(shù)參數(shù)的值,局部變量的值籽御。

2.2 堆區(qū)(heap)

由程序員自己申請分配和釋放练慕,需要malloc()、calloc()技掏、realloc()函數(shù)來申請铃将,用free()函數(shù)來釋放如果不釋放,可能出現(xiàn)指針懸空/野指針哑梳。
函數(shù)不能返回指向棧區(qū)的指針劲阎,但是可以返回指向堆區(qū)的指針。

2.3 數(shù)據(jù)區(qū)(data)

變量標有static關(guān)鍵字鸠真,保存了靜態(tài)變量悯仙。

  1. 初始化的全局變量和初始化的靜態(tài)變量,在一塊區(qū)域吠卷;
  2. 未初始化的全局變量和未初始化的靜態(tài)變量锡垄,在一塊區(qū)域,稱作BSS(Block Started by Symbol:以符號開始的塊)祭隔;
  3. 靜態(tài)變量的生命周期是整個源程序货岭,而且只能被初始化一次,之后的初始化會被忽略疾渴。
    (如果不初始化千贯,數(shù)值數(shù)據(jù)將被默認初始化為0, 字符型數(shù)據(jù)默認初始化為NULL)。
    整個數(shù)據(jù)區(qū)的數(shù)組搞坝,在程序結(jié)束后由系統(tǒng)統(tǒng)一銷毀搔谴。

2.4 代碼區(qū)(code)

用于存放編譯后的可執(zhí)行代碼,二進制碼桩撮,機器碼己沛。

3. 堆和棧的區(qū)別

NO. 比較方面
1 管理方式 由系統(tǒng)自動管理,以執(zhí)行函數(shù)為單位 由程序員手動控制
2 空間大小 空間大小編譯時確定(參數(shù)+局部變量) 具有全局性距境,總體無大小限制申尼。
3 分配方式 函數(shù)執(zhí)行,系統(tǒng)自動分配垫桂;函數(shù)結(jié)束师幕,系統(tǒng)立即自動回收。 使用new/malloc()手動分配釋放;使用delete/free()手動釋放
4 優(yōu)點 使用方便霹粥,不需要關(guān)心內(nèi)存申請釋放灭将。 可以跨函數(shù)使用。
5 缺點 只能在函數(shù)內(nèi)部使用后控。 容易造成內(nèi)存泄露庙曙。

4. 顯示目標文件區(qū)段大小:size命令

各區(qū)段含義

No. 區(qū)段 名稱 含義
1 text 代碼段(code segment/text segment) 存放程序執(zhí)行代碼的內(nèi)存區(qū)域浩淘。該區(qū)域的大小在運行前已確定捌朴,且通常屬于只讀≌懦可能包含一些只讀的常數(shù)變量砂蔽,例如字符串常量等。
2 data 數(shù)據(jù)段(data segment) 存放程序中已初始化的全局變量的內(nèi)存區(qū)域署惯。數(shù)據(jù)段屬于靜態(tài)內(nèi)存分配左驾。
3 bss BSS段(bss segment) 存放程序中未初始化的全局變量的內(nèi)存區(qū)域。BSS是英文Block Started by Symbol的簡稱极谊。BSS段屬于靜態(tài)內(nèi)存分配诡右。

dec與hex是前面三個區(qū)域的和,dec是十進制轻猖,hex是十六進制稻爬。

No. 區(qū)段 含義
1 棧(stack) 存放程序臨時創(chuàng)建的局部變量,也就是函數(shù)括弧{}中定義的變量(不包括static聲明的變量)蜕依。在函數(shù)被調(diào)用時桅锄,參數(shù)也會被壓入發(fā)起調(diào)用的進程棧中,并且待到調(diào)用結(jié)束后样眠,函數(shù)的返回值也會被存放回棧中友瘤。
2 堆(heap) 存放程序動態(tài)分配的內(nèi)存段,大小并不固定檐束,可動態(tài)擴張或縮減辫秧。當調(diào)用malloc()等函數(shù)分配內(nèi)存時,堆被擴張被丧;當調(diào)用free()等函數(shù)釋放內(nèi)存時盟戏,堆被縮減。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甥桂,一起剝皮案震驚了整個濱河市柿究,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌黄选,老刑警劉巖蝇摸,帶你破解...
    沈念sama閱讀 210,835評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡貌夕,警方通過查閱死者的電腦和手機律歼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,900評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來啡专,“玉大人险毁,你說我怎么就攤上這事∶峭” “怎么了畔况?”我有些...
    開封第一講書人閱讀 156,481評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長病附。 經(jīng)常有香客問我,道長亥鬓,這世上最難降的妖魔是什么完沪? 我笑而不...
    開封第一講書人閱讀 56,303評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮嵌戈,結(jié)果婚禮上覆积,老公的妹妹穿的比我還像新娘。我一直安慰自己熟呛,他們只是感情好宽档,可當我...
    茶點故事閱讀 65,375評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著庵朝,像睡著了一般吗冤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上九府,一...
    開封第一講書人閱讀 49,729評論 1 289
  • 那天椎瘟,我揣著相機與錄音,去河邊找鬼侄旬。 笑死肺蔚,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的儡羔。 我是一名探鬼主播宣羊,決...
    沈念sama閱讀 38,877評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼汰蜘!你這毒婦竟也來了仇冯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,633評論 0 266
  • 序言:老撾萬榮一對情侶失蹤族操,失蹤者是張志新(化名)和其女友劉穎赞枕,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,088評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡炕婶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,443評論 2 326
  • 正文 我和宋清朗相戀三年姐赡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柠掂。...
    茶點故事閱讀 38,563評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡项滑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涯贞,到底是詐尸還是另有隱情枪狂,我是刑警寧澤,帶...
    沈念sama閱讀 34,251評論 4 328
  • 正文 年R本政府宣布宋渔,位于F島的核電站州疾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏皇拣。R本人自食惡果不足惜严蓖,卻給世界環(huán)境...
    茶點故事閱讀 39,827評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望氧急。 院中可真熱鬧颗胡,春花似錦、人聲如沸吩坝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,712評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钉寝。三九已至弧呐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嵌纲,已是汗流浹背泉懦。 一陣腳步聲響...
    開封第一講書人閱讀 31,943評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留疹瘦,地道東北人崩哩。 一個月前我還...
    沈念sama閱讀 46,240評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像言沐,于是被迫代替她去往敵國和親邓嘹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,435評論 2 348

推薦閱讀更多精彩內(nèi)容