C/C++中內(nèi)存結(jié)構(gòu)

C/C++編譯的程序占用的內(nèi)存分為以下幾個部分

1柄慰、棧區(qū)(stack)—由編譯器自動分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等食侮。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧荷并。

2合砂、堆區(qū)(heap)—一般由程序員分配釋放,若程序員不釋放源织,程序結(jié)束時可能由OS回收翩伪。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事微猖,分配方式倒是類似于鏈表。

棧(stack)和堆(heap)比較

1.申請方式和回收方式不同

棧是系統(tǒng)自動分配空間的缘屹,例如我們定義一個 char a凛剥;系統(tǒng)會自動在棧上為其開辟空間。而堆則是程序員根據(jù)需要自己申請的空間轻姿,例如malloc(10)犁珠;開辟十個字節(jié)的空間。由于棧上的空間是自動分配自動回收的踢代,所以棧上的數(shù)據(jù)的生存周期只是在函數(shù)的運(yùn)行過程中盲憎,運(yùn)行后就釋放掉,不可以再訪問胳挎。而堆上的數(shù)據(jù)只要程序員不釋放空間饼疙,就一直可以訪問到,不過缺點(diǎn)是一旦忘記釋放會造成內(nèi)存泄露慕爬。

2.申請后系統(tǒng)的響應(yīng)

棧:只要棧的剩余空間大于所申請空間窑眯,系統(tǒng)將為程序提供內(nèi)存,否則將報異常提示棧溢出医窿。

堆:首先應(yīng)該知道操作系統(tǒng)有一個記錄空閑內(nèi)存地址的鏈表磅甩,當(dāng)系統(tǒng)收到程序的申請時,會遍歷該鏈表姥卢,尋找第一個空間大于所申請空間的堆結(jié)點(diǎn)卷要,然后將該結(jié)點(diǎn)從空閑結(jié)點(diǎn)鏈表中刪除,并將該結(jié)點(diǎn)的空間分配給程序独榴,另外僧叉,對于大多數(shù)系統(tǒng),會在這塊內(nèi)存空間中的首地址處記錄本次分配的大小棺榔,這樣才能正確的釋放本內(nèi)存空間瓶堕。另外,由于找到的堆結(jié)點(diǎn)的大小不一定正好等于申請的大小症歇,系統(tǒng)會自動的將多余的那部分重新放入空閑鏈表中郎笆。也就是說堆會在申請后還要做一些后續(xù)的工作這就會引出申請效率的問題。

2.申請效率的比較

根據(jù)第0點(diǎn)和第1點(diǎn)可知忘晤。

棧:棧是機(jī)器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu)宛蚓,計算機(jī)會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執(zhí)行设塔,這就決定了棧的效率比較高苍息。

堆:是由new分配的內(nèi)存,一般速度比較慢,它是通過鏈表的方式尋找可用的內(nèi)存空間竞思,容易產(chǎn)生內(nèi)存碎片,不過用起來最方便表谊,效率低。

3.申請大小的限制

棧:在Windows下,棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)盖喷,是一塊連續(xù)的內(nèi)存的區(qū)域爆办。這句話的意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的,在 WINDOWS下课梳,棧的大小是2M(也有的說是1M距辆,總之是一個編譯時就確定的常數(shù)),如果申請的空間超過棧的剩余空間時暮刃,將提示overflow跨算。因此,能從棧獲得的空間較小椭懊。

堆:堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)诸蚕,是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)是用鏈表來存儲的空閑內(nèi)存地址的氧猬,自然是不連續(xù)的背犯,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計算機(jī)系統(tǒng)中有效的虛擬內(nèi)存盅抚。由此可見漠魏,堆獲得的空間比較靈活,也比較大妄均。

4.堆和棧中的存儲內(nèi)容

棧: 在函數(shù)調(diào)用時柱锹,第一個進(jìn)棧的是主函數(shù)中函數(shù)調(diào)用后的下一條指令(函數(shù)調(diào)用語句的下一條可執(zhí)行語句)的地址,然后是函數(shù)的各個參數(shù)丰包,在大多數(shù)的C編譯器中奕纫,參數(shù)是由右往左入棧的,然后是函數(shù)中的局部變量烫沙。注意靜態(tài)變量是不入棧的。

當(dāng)本次函數(shù)調(diào)用結(jié)束后隙笆,局部變量先出棧锌蓄,然后是參數(shù),最后棧頂指針指向最開始存的地址撑柔,也就是主函數(shù)中的下一條指令瘸爽,程序由該點(diǎn)繼續(xù)運(yùn)行。

堆:一般是在堆的頭部用一個字節(jié)存放堆的大小铅忿。堆中的具體內(nèi)容有程序員安排剪决。

5.分配方式

堆都是動態(tài)分配的,沒有靜態(tài)分配的堆。棧有2種分配方式:靜態(tài)分配和動態(tài)分配柑潦。靜態(tài)分配是編譯器完成的享言,比如局部變量的分配。動態(tài)分配由alloca函數(shù)進(jìn)行分配渗鬼,但是棧的動態(tài)分配和堆是不同的览露,他的動態(tài)分配是由編譯器進(jìn)行釋放,無需我們手工實(shí)現(xiàn)譬胎。

3差牛、全局區(qū)(靜態(tài)區(qū))(static)—,全局變量和靜態(tài)變量的存儲是放在一塊的堰乔,初始化的全局變量和靜態(tài)變量在一塊區(qū)域偏化,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。

- 程序結(jié)束后由系統(tǒng)釋放镐侯。

4侦讨、文字常量區(qū)—常量字符串就是放在這里的。程序結(jié)束后由系統(tǒng)釋放

5析孽、程序代碼區(qū)—存放函數(shù)體的二進(jìn)制代碼搭伤。

代碼演示

int a = 0; 全局初始化區(qū)

char *p1; 全局未初始化區(qū)

{int b; 棧

char *p3 = "123456"; 123456\0在常量區(qū),p3在棧上袜瞬。

static int c =0怜俐; 全局(靜態(tài))初始化區(qū)

p1 = (char *)malloc(10); p1指向的數(shù)據(jù)分配在堆區(qū)(p1本身分配在靜態(tài)區(qū))。

}

接下來我們探討一下c語言中char *str 與char str[]有什么區(qū)別

char* test(){

char * str = "abcdefg";

return str;

}

等號右邊存放在常量區(qū)邓尤,等號左邊的str是局部變量所以存放在棧內(nèi)存拍鲤,str指向存放"abcdefg"的內(nèi)存區(qū)域。函數(shù)結(jié)束時這塊區(qū)域并不會釋放汞扎。

char* test(){

char? str[] = "abcdefg";

return str;

}

等號右邊依然存放在常量區(qū)季稳,等號左邊是一個字符型數(shù)組,盡管是數(shù)組澈魄,但它是一個局部變量景鼠,所以會在棧區(qū)分配一塊內(nèi)存存儲這個數(shù)組,然后將常量區(qū)的"abcdefg"拷貝過來痹扇,這樣就會導(dǎo)致函數(shù)執(zhí)行完畢之后這塊內(nèi)存會被釋放掉铛漓,那么這個數(shù)組也就不存在了。

總結(jié)

使用棧就象我們?nèi)ワ堭^里吃飯鲫构,只管點(diǎn)菜(發(fā)出申請)浓恶、付錢、和吃(使用)结笨,吃飽了就走包晰,不必理會切菜湿镀、洗菜等準(zhǔn)備工作和洗碗、刷鍋等掃尾工作伐憾,他的好處是快捷勉痴,但是自由度小。

使用堆就象是自己動手做喜歡吃的菜肴塞耕,比較麻煩蚀腿,但是比較符合自己的口味,而且自由度大扫外。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末莉钙,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子筛谚,更是在濱河造成了極大的恐慌磁玉,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驾讲,死亡現(xiàn)場離奇詭異蚊伞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)吮铭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門时迫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人谓晌,你說我怎么就攤上這事掠拳。” “怎么了纸肉?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵溺欧,是天一觀的道長。 經(jīng)常有香客問我柏肪,道長姐刁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任烦味,我火速辦了婚禮聂使,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谬俄。我一直安慰自己柏靶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布凤瘦。 她就那樣靜靜地躺著,像睡著了一般案铺。 火紅的嫁衣襯著肌膚如雪蔬芥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機(jī)與錄音笔诵,去河邊找鬼返吻。 笑死,一個胖子當(dāng)著我的面吹牛乎婿,可吹牛的內(nèi)容都是我干的测僵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼谢翎,長吁一口氣:“原來是場噩夢啊……” “哼捍靠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起森逮,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤榨婆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后褒侧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體良风,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年闷供,在試婚紗的時候發(fā)現(xiàn)自己被綠了烟央。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡歪脏,死狀恐怖疑俭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情唾糯,我是刑警寧澤怠硼,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站移怯,受9級特大地震影響香璃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜舟误,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一葡秒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嵌溢,春花似錦眯牧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至秧骑,卻和暖如春版确,著一層夾襖步出監(jiān)牢的瞬間扣囊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工绒疗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留侵歇,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓吓蘑,卻偏偏與公主長得像惕虑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子磨镶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355

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

  • C語言中內(nèi)存分配 在任何程序設(shè)計環(huán)境及語言中溃蔫,內(nèi)存管理都十分重要。在目前的計算機(jī)系統(tǒng)或嵌入式系統(tǒng)中棋嘲,內(nèi)存資源仍然是...
    一生信仰閱讀 1,162評論 0 2
  • (JG-2014-08-20)(前半部分經(jīng)過網(wǎng)上多篇文章對比整理)(后半部分根據(jù)ExceptionalCpp酒唉、C+...
    JasonGao閱讀 5,605評論 2 23
  • 或許這就是長大吧,當(dāng)你看著身邊一個接一個的老人接連離去的時候沸移,從一開始的慌亂痪伦,到最后的鎮(zhèn)靜,一步步都是在為了讓你熟...
    不來常思君閱讀 148評論 0 0
  • 最近遇到了很多事情,工作上的事情蕊爵、生活上的事情都是一團(tuán)糟辉哥。在這種混亂的狀態(tài)下,我一直在梳理事情至此的原因攒射,以及如何...
    Kategogo閱讀 487評論 0 0
  • r1第二十一天-20171029今天完成了第一個21天精進(jìn)醋旦!值得慶祝!終于握住了能幫助逃離泥沼的救命繩会放!應(yīng)該獎勵自...