內存分配——靜態存儲區 棧 堆

一、內存基本構成

可編程內存在基本上分為這樣的幾大部分:靜態存儲區、堆區和棧區。他們的功能不同,對他們使用方式也就不同。

靜態存儲區:內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。它主要存放靜態數據、全局數據和常量。

棧區:在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。

堆區:亦稱動態內存分配。程序在運行的時候用malloc或new申請任意大小的內存,程序員自己負責在適當的時候用free或delete釋放內存。動態內存的生存期可以由我們決定,如果我們不釋放內存,程序將在最后才釋放掉動態內存。 但是,良好的編程習慣是:如果某動態內存不再使用,需要將其釋放掉,否則,我們認為發生了內存泄漏現象。

代碼區:存放函數體的二進制代碼

文字常量區? —常量字符串就是放在這里的。 程序結束后由系統釋放

函數指針指向Code區,是程序運行的指令代碼,數據指針指向Data,Heap,Stack區,是程序依賴以運行的各種數據

在文件作用域聲明inline函數默認為static存儲類型,const常量默認為static存儲,如果加上extern,則為外部存儲類型。

二、三者之間的區別

我們通過代碼段來看看對這樣的三部分內存需要怎樣的操作和不同,以及應該注意怎樣的地方。

例一:靜態存儲區與棧區

char* p = “Hello World1”;

char a[] = “Hello World2”;

p[2] = ‘A’;

a[2] = ‘A’;

char* p1 = “Hello World1;”

這個程序是有錯誤的,錯誤發生在p[2] = ‘A’這行代碼處,為什么呢,是變量p和變量數組a都存在于棧區的(任何臨時變量都是處于棧區的,包括在main()函數中定義的變量)。但是,數據“Hello World1”和數據“Hello World2”是存儲于不同的區域的。

因為數據“Hello World2”存在于數組中,所以,此數據存儲于棧區,對它修改是沒有任何問題的。因為指針變量p僅僅能夠存儲某個存儲空間的地址,數據“Hello World1”為字符串常量,所以存儲在靜態存儲區。雖然通過p[2]可以訪問到靜態存儲區中的第三個數據單元,即字符‘l’所在的存儲的單元。但是因為數據“Hello World1”為字符串常量,不可以改變,所以在程序運行時,會報告內存錯誤。并且,如果此時對p和p1輸出的時候會發現p和p1里面保存的地址是完全相同的。換句話說,在數據區只保留一份相同的數據

例二:棧區與堆區

char* f1()

{

char* p = NULL;

char a;

p = &a;

return p;

}

char* f2()

{

char* p = NULL:

p =(char*) new char[4];

return p;

}

這兩個函數都是將某個存儲空間的地址返回,二者有何區別呢?f1()函數雖然返回的是一個存儲空間,但是此空間為臨時空間。也就是說,此空間只有短暫的生命周期,它的生命周期在函數f1()調用結束時,也就失去了它的生命價值,即:此空間被釋放掉。所以,當調用f1()函數時,如果程序中有下面的語句:

char* p ;

p = f1();

*p = ‘a’;

此時,編譯并不會報告錯誤,但是在程序運行時,會發生異常錯誤。因為,你對不應該操作的內存(即,已經釋放掉的存儲空間)進行了操作。但是,相比之下,f2()函數不會有任何問題。因為,new這個命令是在堆中申請存儲空間,一旦申請成功,除非你將其delete或者程序終結,這塊內存將一直存在。也可以這樣理解,堆內存是共享單元,能夠被多個函數共同訪問。如果你需要有多個數據返回卻苦無辦法,堆內存將是一個很好的選擇。但是一定要避免下面的事情發生:

void f()

{

char * p;

p = (char*)new char[100];

}

這個程序做了一件很無意義并且會帶來很大危害的事情。因為,雖然申請了堆內存,p保存了堆內存的首地址。但是,此變量是臨時變量,當函數調用結束時p變量消失。也就是說,再也沒有變量存儲這塊堆內存的首地址,我們將永遠無法再使用那塊堆內存了。但是,這塊堆內存卻一直標識被你所使用(因為沒有到程序結束,你也沒有將其delete,所以這塊堆內存一直被標識擁有者是當前您的程序),進而其他進程或程序無法使用。我們將這種不道德的“流氓行為”(我們不用,卻也不讓別人使用)稱為內存泄漏。這是我們C++程序員的大忌!!請大家一定要避免這件事情的發生。

總之,對于堆區、棧區和靜態存儲區它們之間最大的不同在于,棧的生命周期很短暫。但是堆區和靜態存儲區的生命周期相當于與程序的生命同時存在(如果您不在程序運行中間將堆內存delete的話),我們將這種變量或數據成為全局變量或數據。但是,對于堆區的內存空間使用更加靈活,因為它允許你在不需要它的時候,隨時將它釋放掉,而靜態存儲區將一直存在于程序的整個生命周期中。


另外,補充一篇介紹內存分配的文章,也是轉發率很高的一篇 http://blog.csdn.net/hairetz/article/details/4141043

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,963評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,348評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,083評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,706評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,442評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,802評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,795評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,983評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,542評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,287評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,486評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,030評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,710評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,116評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,412評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,224評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,462評論 2 378

推薦閱讀更多精彩內容