計(jì)算機(jī)中的內(nèi)存是分區(qū)來管理的铲球,程序和程序之間的內(nèi)存是獨(dú)立的,不能互相訪問晰赞,比如QQ和瀏覽器分別所占的內(nèi)存區(qū)域是不能相互訪問的稼病。而每個(gè)程序的內(nèi)存也是分區(qū)管理的,一個(gè)應(yīng)用程序所占的內(nèi)存可以分為很多個(gè)區(qū)域掖鱼,我們需要了解的主要有四個(gè)區(qū)域然走,通常叫內(nèi)存四區(qū),如下圖:
在C語言中戏挡,內(nèi)存的主要分為下列幾部分:
Text/Code Segment 文本/代碼區(qū)
Initialized Data Segments 初始化的數(shù)據(jù)區(qū)
Uninitialized Data Segments 未初始化的數(shù)據(jù)區(qū)
Stack Segment 棧區(qū)
Heap Segment 堆區(qū)
Text/Code Segment 文本/代碼區(qū)
這個(gè)區(qū)主要用來保存機(jī)器代碼芍瑞,一個(gè)可執(zhí)行對象文件的文本區(qū)通常是只讀區(qū),可以防止程序被意外修改褐墅。文本/代碼區(qū)可能會被放在堆和棧的下方來防止堆和棧的覆寫溢出拆檬。
Initialized Data Segments 初始化的數(shù)據(jù)區(qū)
初始化的數(shù)據(jù)區(qū)存儲了所有的初始化了的全局的洪己,靜態(tài)的,常量的秩仆,外部的變量码泛。這些變量沒有在函數(shù)內(nèi)部定義或者是以靜態(tài)的方式在函數(shù)內(nèi)部定義了猾封,比如下面兩種情況:
int val = 3;
char string[] = "Hello World";
這些變量最初是保存在只讀內(nèi)存中(Text/Code Segment 文本/代碼區(qū)中)澄耍,然后被拷貝到了初始化的數(shù)據(jù)區(qū)。
Uninitialized Data Segments 未初始化的數(shù)據(jù)區(qū)
未初始化的數(shù)據(jù)區(qū)晌缘,又稱作BSS (Block Started by Symbol)齐莲,這個(gè)區(qū)一般緊連著初始化的數(shù)據(jù)區(qū),用來保存所有的初始化為0的全局變量和靜態(tài)變量磷箕,或者沒有初始化选酗,比如 static int i;
將會存在BSS中。BSS段屬于靜態(tài)內(nèi)存分配岳枷。
Stack Segment 棧區(qū)
棧區(qū)是緊連著堆區(qū)的芒填,堆和棧的增長方向相反,當(dāng)堆和棧的指針重合時(shí)空繁,此時(shí)內(nèi)存被耗盡殿衰。棧區(qū)是以后進(jìn)先出(LIFO)的機(jī)制運(yùn)行的,通常在內(nèi)存的高地址處盛泡。當(dāng)一個(gè)函數(shù)被調(diào)用時(shí)闷祥,該函數(shù)的返回地址和調(diào)用者的環(huán)境信息被保存在棧中,新調(diào)用的函數(shù)再在棧上開辟空間保存自動(dòng)和臨時(shí)變量傲诵,這就是遞歸函數(shù)的運(yùn)行機(jī)制凯砍。當(dāng)一個(gè)遞歸函數(shù)調(diào)用它本身時(shí),一個(gè)新的棧格被使用拴竹,所以這些變量不會跟上次遞歸的變量相互干擾悟衩。棧區(qū)主要保存一些局部變量。
每個(gè)線程都有自己專屬的棧
棧的最大尺寸固定栓拜,超出則引起棧溢出
變量離開作用域后棧上的內(nèi)存會自動(dòng)釋放
Heap Segment 堆區(qū)
堆區(qū)主要用來動(dòng)態(tài)分配內(nèi)存座泳。通過malloc, realloc和free來管理。堆區(qū)被所有線程菱属,公用庫钳榨,動(dòng)態(tài)加載模塊所共享。
Stack and Heap 堆和棧的區(qū)別
在和計(jì)算機(jī)內(nèi)存打交道時(shí)纽门,我們一定會碰到堆和棧薛耻,這兩個(gè)東西很容易搞混,那么現(xiàn)在就來梳理一下二者的關(guān)系赏陵。
棧是用來靜態(tài)分配內(nèi)存的而堆是動(dòng)態(tài)分配內(nèi)存的饼齿,它們都是存在于計(jì)算機(jī)內(nèi)存之中饲漾。
棧的分配是在程序編譯的時(shí)候完成的,直接存儲在內(nèi)存中缕溉,接觸內(nèi)存很快考传。棧是后進(jìn)先出的順序,最后被申請的塊最先被釋放证鸥,這樣就很容易跟蹤到棧僚楞,釋放棧的過程簡單到僅僅是移動(dòng)下指針就能完成。
堆的分配是在程序運(yùn)行時(shí)完成的枉层,分配速度較為緩慢泉褐,但是堆的可用空間非常的大。堆中的元素相互之間沒有關(guān)聯(lián)鸟蜡,各自都可以被任何時(shí)候隨機(jī)訪問膜赃。我們可以任何時(shí)候申請和釋放一塊內(nèi)存,這樣會使得我們很難隨時(shí)隨地追蹤到堆中某塊位置被分配了還是被釋放了揉忘。
當(dāng)你知道在編譯前需要分配多少數(shù)據(jù)時(shí)且數(shù)據(jù)量不是很大時(shí)可以使用棧跳座。如果不知道在運(yùn)行時(shí)需要多少數(shù)據(jù)那么就該使用堆。
在多線程的程序里泣矛,每個(gè)線程都有其自己獨(dú)立的棧疲眷,它們都共享一個(gè)堆。棧是面向線程的而堆是面向進(jìn)程的乳蓄。
程序咪橙、可執(zhí)行文件與進(jìn)程空間映射
... ...