C語(yǔ)言內(nèi)存管理_第1頁(yè)
C語(yǔ)言內(nèi)存管理_第2頁(yè)
C語(yǔ)言內(nèi)存管理_第3頁(yè)
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、C 語(yǔ)言內(nèi)存管理Revised by Petrel at 2021C語(yǔ)言程序編譯的內(nèi)存分配:1 ?棧區(qū) stack - 編譯器自動(dòng)分配釋放,主要存放函數(shù)的參數(shù)值,局部變量值2?堆區(qū)heap 一由程序員分配釋放;3?全局區(qū)或靜態(tài)區(qū)一存放全局變量和靜態(tài)變量;程序結(jié)束時(shí)山系統(tǒng)釋放,分為全 局初始化區(qū)和全局未初始化區(qū);4?字符常量區(qū)一常量字符串放與此,程序結(jié)束時(shí)山系統(tǒng)釋放;5.程序代碼區(qū)一存放函數(shù)體的二進(jìn)制代碼例:/main, cint a=0; / 全局初始化區(qū)char *pl; / 全局未初始化區(qū)void main int b; 棧char s 二"bb" / 棧char *p

2、2; / 棧char *p3 二 123" / 其中,“ 123 0 常量區(qū), p3 在棧區(qū)static int c=0; / 全局區(qū)pl= char* malloc 10; /10 個(gè)字節(jié)區(qū)域在堆區(qū) strcpy pl/ /123O; 123T在常量區(qū),編譯器 可能 會(huì)優(yōu)化為和p3的指向同一 塊區(qū)域一個(gè)C程序占用的內(nèi)存可分為以下兒類:一棧這是山編譯器自動(dòng)分配和釋放的區(qū)域。主要存儲(chǔ)函數(shù)的參數(shù),函數(shù)的局部變量 等。當(dāng)一個(gè)函數(shù)開始執(zhí)行時(shí),該函數(shù)所需的實(shí)參,局部變量就推入棧中,該函數(shù)執(zhí) 行完畢后,之前進(jìn)入棧中的參數(shù)和變量等也都出棧被釋放掉。它的運(yùn)行方式類似于 數(shù)據(jù)結(jié)構(gòu)中的棧。二堆這是山程序

3、員控制分配和釋放的區(qū)域,在C里,用mallocO函數(shù)分配的空間就存在于堆上。在堆上分配的空間不像棧一樣在某個(gè)函數(shù)執(zhí)行完畢就自動(dòng)釋放,而 是一直存在于整個(gè)程序的運(yùn)行期間。當(dāng)然,如果你不手動(dòng)釋放 free 函數(shù) 這些空間,在程序運(yùn)行結(jié)束后系統(tǒng)也會(huì)將之自動(dòng)釋放。對(duì)于小程序來說可能感覺 不到影響的存在,但對(duì)于大程序,例如一個(gè)大型游戲,就會(huì)遇到內(nèi)存不夠用的問 題了三全局區(qū)C里的全局變量和靜態(tài)變量存儲(chǔ)在全局區(qū)。它們有點(diǎn)像堆上的空間,也是持續(xù) 存在于程序的整個(gè)運(yùn)行期間,但不同的是,他們是山編譯器自己控制分配和釋放 的。四文字常量區(qū)例如 ch 孔紋二“123456;那么123456"為文字常量,存放

4、于文字常量區(qū)。也山編譯器控制分配和釋放。五程序代碼區(qū)存放函數(shù)體的二進(jìn)制代碼。2. 例子( 一)int a = 0; / 全局區(qū)void main()int b; 棧char s = "abc"s 在棧,冷 be" 在文字常量區(qū)char *pl, *p2; 棧char *p3 = "123456" /"123456" 在常量區(qū), p3 在棧上 static int c 二 0; / 全局區(qū)pl = (char *)malloc(10) ; /pl 在棧,分配的 10 字節(jié)在堆 p2 = (char *)malloc(20);

5、/p2 在棧,分配的 20 字節(jié)在堆 strcpy(pl, ,z123456,z); / “123456"放在常量區(qū) 編譯器可能將它與 P3 所指向的 "123456"優(yōu)化成一個(gè)地 方。3. 例子( 二)返回 char 型指針char *f ()/s 數(shù)組存放于棧上char s4 二T ,''O' ;return s; 返回 s 數(shù)組的地址,但程序運(yùn)行完 s 數(shù)組就被釋放了 void main()char *s; s 二 f ();printf (z%s s); / 打印出來亂碼。因?yàn)?s 所指向地址已經(jīng)沒有數(shù)據(jù)還有就是函數(shù)調(diào)用時(shí)會(huì)在棧上有

6、一系列的保存現(xiàn)場(chǎng)及傳遞參數(shù)的操作。 棧的空間大小有限定,vc的缺省是2M棧不夠用的情況一般是程序中分配了大量 數(shù)組和遞歸函數(shù)層次太深。有一點(diǎn)必須知道,當(dāng)一個(gè)函數(shù)調(diào)用完返回后它會(huì)釋放該 函數(shù)中所有的棧空間。棧是由編譯器自動(dòng)管理的,不用你操心。堆是動(dòng)態(tài)分配內(nèi)存的,并且你可以分配使用很大的內(nèi)存。但是用不好會(huì)產(chǎn)生內(nèi) 存泄漏。并且頻繁地 malloc 和 free 會(huì)產(chǎn)生內(nèi)存碎片 ( 有點(diǎn)類似磁盤碎片 ) ,因?yàn)?C 分配動(dòng)態(tài)內(nèi)存時(shí)是尋找匹配的內(nèi)存的。而用棧那么不會(huì)產(chǎn)生碎片,在棧上存取數(shù)據(jù) 比通過指針在堆上存取數(shù)據(jù)快些。一般大家說的堆棧和棧是一樣的,就是棧 (stack),而說堆時(shí)才是堆heap?棧是先

7、入后出的,一般是山高地址向低地址生 長(zhǎng)。堆(heap)和棧(stack )是C/C編程不可防止會(huì)碰到的兩個(gè)根本概念。首 先, 這兩個(gè)概念都可以在講數(shù)據(jù)結(jié)構(gòu)的書中找到,他們都是根本的數(shù)據(jù)結(jié)構(gòu),雖 然棧更 為簡(jiǎn)單一些。在具體的C/C編程框架中,這兩個(gè)概念并不是并行的。對(duì)底 層機(jī)器 代碼的研究可以揭示,棧是機(jī)器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu),而堆那么是C/C函數(shù)庫(kù)提供 的。具體地說,現(xiàn)代計(jì)算機(jī)(串行執(zhí)行機(jī)制),都直接在代碼底層支持棧的數(shù)據(jù)結(jié) 構(gòu)。這表達(dá)在,有專門的存放器指向棧所在的地址,有專門的機(jī)器指令 完成數(shù)據(jù)入 棧出棧的操作。種機(jī)制的特點(diǎn)是效率高,支持的數(shù)據(jù)有限,一般是整 數(shù),指針,浮 點(diǎn)數(shù)等系統(tǒng)直接支持的

8、數(shù)據(jù)類型,并不直接支持其他的數(shù)據(jù)結(jié)構(gòu)。 因?yàn)闂5倪@種特 點(diǎn),對(duì)棧的使用在程序中是非常頻繁的。對(duì)子程序的調(diào)用就是直 接利用棧完成的。 機(jī)器的 call 指令里隱含了把返回地址推入棧,然后跳轉(zhuǎn)至子程 序地址的操作,而 子程序中的 ret 指令那么隱含從堆棧中彈岀返回地址并跳轉(zhuǎn)之的 操作。 C/C 中的自 動(dòng)變量是直接利棧的例子,這也就是為什么當(dāng)函數(shù)返回時(shí),該 函數(shù)的自動(dòng)變量自動(dòng) 失效的原因。和棧不同,堆的數(shù)據(jù)結(jié)構(gòu)并不是山系統(tǒng)無論是機(jī)器系統(tǒng)還是操作系統(tǒng)支持 的,而是山函數(shù)庫(kù)提供的。根本的 malloc/realloc/free 函數(shù)維護(hù)了一套內(nèi)部的堆 數(shù)據(jù)結(jié)構(gòu)。當(dāng)程序使用這些函數(shù)去獲得新的內(nèi)存空間時(shí)

9、,這套函數(shù)首先試圖從內(nèi)部 堆中尋找可用的內(nèi)存空間,如果沒有可以使用的內(nèi)存空間,那么試圖利用系統(tǒng)調(diào)用來 動(dòng)態(tài)增加程序數(shù)據(jù)段的內(nèi)存大小,新分配得到的空間首先被組織進(jìn)內(nèi)部堆中去,然 后再以適當(dāng)?shù)男问椒祷亟o調(diào)用者。當(dāng)程序釋放分配的內(nèi)存空間時(shí),這片內(nèi)存空間被 返回內(nèi)部堆結(jié)構(gòu)中,可能會(huì)被適當(dāng)?shù)奶幚肀确胶推渌臻e空間合并成更大的空閑 空間,以更適合下一次內(nèi)存分配申請(qǐng)。這套復(fù)雜的分配機(jī)制實(shí)際上相當(dāng)于一個(gè)內(nèi) 存分配的緩沖池 Cache, 使用這套機(jī)制有如下假設(shè)干原因:1. 系統(tǒng)調(diào)用可能不支持任意大小的內(nèi)存分配。有些系統(tǒng)的系統(tǒng)調(diào)用只支持固定大 小及其倍數(shù)的內(nèi)存請(qǐng)求按頁(yè)分配 : 這樣的話對(duì)于大量的小內(nèi)存分類來說會(huì)造成 浪 3?系統(tǒng)調(diào)用申請(qǐng)內(nèi)存可能是代價(jià)昂貴的。系統(tǒng)調(diào)用可能涉及用戶態(tài)和核心態(tài)的轉(zhuǎn) 換。3. 沒有管理的內(nèi)存分配在大量復(fù)雜內(nèi)存的分配釋放操作下很容易造成內(nèi)存碎片 堆 和棧的比照從以上知識(shí)可知,棧是系統(tǒng)提供的功能,特點(diǎn)是快速高效,缺點(diǎn)是有限制,數(shù) 據(jù)不靈活;而堆是函數(shù)庫(kù)提供的功能,特點(diǎn)是靈活方便,數(shù)據(jù)適應(yīng)面廣泛,但是效 率有一定降低。棧是系統(tǒng)數(shù)據(jù)結(jié)構(gòu),對(duì)于進(jìn)程 / 線程是唯一的;堆是函數(shù)庫(kù)內(nèi)部數(shù) 據(jù)結(jié)構(gòu),不一定唯一。不同堆分配的內(nèi)存無法互相操作。??臻g分靜態(tài)分配和動(dòng)態(tài) 分配兩種。靜態(tài)分配是編譯器完成

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論