|
|||||||||||
| 技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測(cè)控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng) 驅(qū)動(dòng)編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機(jī) | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計(jì) | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe |
大家討論內(nèi)存動(dòng)態(tài)分配問題 |
| 作者:db10 欄目:嵌入式系統(tǒng) |
先看看一些基本概念:一、為什么用動(dòng)態(tài)內(nèi)存分配 但我們未學(xué)習(xí)鏈表的時(shí)候,如果要存儲(chǔ)數(shù)量比較多的同類型或同結(jié)構(gòu)的數(shù)據(jù)的時(shí)候,總是使用一個(gè)數(shù)組。比如說我們要存儲(chǔ)一個(gè)班級(jí)學(xué)生的某科分?jǐn)?shù),總是定義一個(gè)float型(存在0.5分)數(shù)組: float score[30]; 但是,在使用數(shù)組的時(shí)候,總有一個(gè)問題困擾著我們:數(shù)組應(yīng)該有多大? 在很多的情況下,你并不能確定要使用多大的數(shù)組,比如上例,你可能并不知道該班級(jí)的學(xué)生的人數(shù),那么你就要把數(shù)組定義得足夠大。這樣,你的程序在運(yùn)行時(shí)就申請(qǐng)了固定大小的你認(rèn)為足夠大的內(nèi)存空間。即使你知道該班級(jí)的學(xué)生數(shù),但是如果因?yàn)槟撤N特殊原因人數(shù)有增加或者減少,你又必須重新去修改程序,擴(kuò)大數(shù)組的存儲(chǔ)范圍。這種分配固定大小的內(nèi)存分配方法稱之為靜態(tài)內(nèi)存分配。但是這種內(nèi)存分配的方法存在比較嚴(yán)重的缺陷,特別是處理某些問題時(shí):在大多數(shù)情況下會(huì)浪費(fèi)大量的內(nèi)存空間,在少數(shù)情況下,當(dāng)你定義的數(shù)組不夠大時(shí),可能引起下標(biāo)越界錯(cuò)誤,甚至導(dǎo)致嚴(yán)重后果。 那么有沒有其它的方法來解決這樣的外呢體呢?有,那就是動(dòng)態(tài)內(nèi)存分配。 所謂動(dòng)態(tài)內(nèi)存分配就是指在程序執(zhí)行的過程中動(dòng)態(tài)地分配或者回收存儲(chǔ)空間的分配內(nèi)存的方法。動(dòng)態(tài)內(nèi)存分配不象數(shù)組等靜態(tài)內(nèi)存分配方法那樣需要預(yù)先分配存儲(chǔ)空間,而是由系統(tǒng)根據(jù)程序的需要即時(shí)分配,且分配的大小就是程序要求的大小。從以上動(dòng)、靜態(tài)內(nèi)存分配比較可以知道動(dòng)態(tài)內(nèi)存分配相對(duì)于景泰內(nèi)存分配的特點(diǎn): 1、不需要預(yù)先分配存儲(chǔ)空間; 2、分配的空間可以根據(jù)程序的需要擴(kuò)大或縮小。 二、如何實(shí)現(xiàn)動(dòng)態(tài)內(nèi)存分配及其管理 要實(shí)現(xiàn)根據(jù)程序的需要?jiǎng)討B(tài)分配存儲(chǔ)空間,就必須用到以下幾個(gè)函數(shù) 1、malloc函數(shù) malloc函數(shù)的原型為: void *malloc (unsigned int size) 其作用是在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)中分配一個(gè)長(zhǎng)度為size的連續(xù)空間。其參數(shù)是一個(gè)無符號(hào)整形數(shù),返回值是一個(gè)指向所分配的連續(xù)存儲(chǔ)域的起始地址的指針。還有一點(diǎn)必須注意的是,當(dāng)函數(shù)未能成功分配存儲(chǔ)空間(如內(nèi)存不足)就會(huì)返回一個(gè)NULL指針。所以在調(diào)用該函數(shù)時(shí)應(yīng)該檢測(cè)返回值是否為NULL并執(zhí)行相應(yīng)的操作。 下例是一個(gè)動(dòng)態(tài)分配的程序: #include #include main() { int count,*array; /*count是一個(gè)計(jì)數(shù)器,array是一個(gè)整型指針,也可以理解為指向一個(gè)整型數(shù)組的首地址*/ if((array(int *) malloc(10*sizeof(int)))==NULL) { printf("不能成功分配存儲(chǔ)空間。"); exit(1); } for (count=0;count〈10;count++) /*給數(shù)組賦值*/ array[count]=count; for(count=0;count〈10;count++) /*打印數(shù)組元素*/ printf("%2d",array[count]); } 上例中動(dòng)態(tài)分配了10個(gè)整型存儲(chǔ)區(qū)域,然后進(jìn)行賦值并打印。例中if((array(int *) malloc(10*sizeof(int)))==NULL)語句可以分為以下幾步: 1)分配10個(gè)整型的連續(xù)存儲(chǔ)空間,并返回一個(gè)指向其起始地址的整型指針 2)把此整型指針地址賦給array 3)檢測(cè)返回值是否為NULL 2、free函數(shù) 由于內(nèi)存區(qū)域總是有限的,不能不限制地分配下去,而且一個(gè)程序要盡量節(jié)省資源,所以當(dāng)所分配的內(nèi)存區(qū)域不用時(shí),就要釋放它,以便其它的變量或者程序使用。這時(shí)我們就要用到free函數(shù)。 其函數(shù)原型是: void free(void *p) 作用是釋放指針p所指向的內(nèi)存區(qū)。 其參數(shù)p必須是先前調(diào)用malloc函數(shù)或calloc函數(shù)(另一個(gè)動(dòng)態(tài)分配存儲(chǔ)區(qū)域的函數(shù))時(shí)返回的指針。給free函數(shù)傳遞其它的值很可能造成死機(jī)或其它災(zāi)難性的后果。 注意:這里重要的是指針的值,而不是用來申請(qǐng)動(dòng)態(tài)內(nèi)存的指針本身。例: int *p1,*p2; p1=malloc(10*sizeof(int)); p2=p1; …… free(p2) /*或者free(p2)*/ malloc返回值賦給p1,又把p1的值賦給p2,所以此時(shí)p1,p2都可作為free函數(shù)的參數(shù)。 malloc函數(shù)是對(duì)存儲(chǔ)區(qū)域進(jìn)行分配的。 free函數(shù)是釋放已經(jīng)不用的內(nèi)存區(qū)域的。 所以由這兩個(gè)函數(shù)就可以實(shí)現(xiàn)對(duì)內(nèi)存區(qū)域進(jìn)行動(dòng)態(tài)分配并進(jìn)行簡(jiǎn)單的管理了。 另外一個(gè)規(guī)擇:malloc與free要成對(duì)出現(xiàn) 它們是一對(duì)恩愛夫妻,malloc少了free就必然會(huì)慢慢地死掉。成對(duì)出現(xiàn)不僅體現(xiàn)在有多少個(gè)malloc就應(yīng)該有多少個(gè)free,還體現(xiàn)在它們應(yīng)盡量出現(xiàn)在同一函數(shù)里,“誰申請(qǐng),就由誰釋放”,看下面的程序: CHAR * func(void) { CHAR *p; p = (CHAR *)malloc(…); if(p!=NULL) …; /* 一系列針對(duì)p的操作 */ return p; } /*在某處調(diào)用func(),用完func中動(dòng)態(tài)申請(qǐng)的內(nèi)存后將其free*/ CHAR *q = func(); … free(q); 上述代碼違反了malloc和free的“誰申請(qǐng),就由誰釋放”原則,代碼的耦合度大,用戶在調(diào)用func函數(shù)時(shí)需確切知道其內(nèi)部細(xì)節(jié)!正確的做法是: /* 在調(diào)用處申請(qǐng)內(nèi)存,并傳入func函數(shù) */ CHAR *p=malloc(…); if(p!=NULL) { func(p); … free(p); p=NULL; } /* 函數(shù)func則接收參數(shù)p */ void func(CHAR *p) { … /* 一系列針對(duì)p的操作 */ } free后一定要置指針為NULL,防止其成為“野”指針 我的使用: 在C51里(不帶操作系統(tǒng))我已經(jīng)是可以做動(dòng)態(tài)分配內(nèi)存的。但是在51實(shí)現(xiàn)動(dòng)態(tài)不像上面說的簡(jiǎn)單,開始也是根據(jù)上面說的做的,但是發(fā)現(xiàn)在51里這樣做是不行的,后來終于實(shí)現(xiàn)了,那時(shí)必須在malloc之前調(diào)用一個(gè)init_mem(具體看KEIL庫(kù)函數(shù)就知道)的函數(shù)分配一個(gè)比較大的空間之后,再用malloc就在這個(gè)已經(jīng)分配的空間可以申請(qǐng)到內(nèi)存了,就可以用malloc和free成對(duì)無限的使用這塊大空間了。其實(shí)在51里說白了就是有限制的不是全自動(dòng)的動(dòng)態(tài)申請(qǐng)內(nèi)存。 問題:現(xiàn)在我在lpc3132里(不帶操作系統(tǒng))這樣用。當(dāng)然不用象我51里一樣init_mem 來先確定一個(gè)大范圍,直接用malloc就可以申請(qǐng)到,并且連續(xù)申請(qǐng)500個(gè)10個(gè)字節(jié)大小的內(nèi)存沒有問題,當(dāng)我用完他的一部分再釋放free一部分。但是現(xiàn)在有個(gè)問題:我做了實(shí)驗(yàn),當(dāng)我連續(xù)申請(qǐng)了5K大小的空間,每次申請(qǐng)的大小是10個(gè)字節(jié),即連續(xù)調(diào)用malloc達(dá)體是500次。我看到都是OK的,但是在然后的使用中,部分的用free 釋放掉,當(dāng)然其中可能又要使用到malloc,這時(shí)使用malloc就申請(qǐng)不到內(nèi)存,但是我用了一個(gè)全局變量,即運(yùn)行一次malloc是加一,運(yùn)行一次free就減一,當(dāng)不能申請(qǐng)時(shí)發(fā)現(xiàn)此時(shí)的這個(gè)全局變量值是才為2。但是為什么申請(qǐng)不到?這個(gè)全局變量值開始malloc次即是500可以的。而中間釋放運(yùn)行free,再malloc就不行,難道free不起作用,在51這樣用為什么可以? |
| 2樓: | >>參與討論 |
| 作者: kanprin 于 2006/6/9 8:18:00 發(fā)布:
LPC有那么大的RAM? 真爽,不知道在哪邊看過的,好像說用malloc來動(dòng)態(tài)管理內(nèi)存會(huì)產(chǎn)生磁盤碎片,可能是這個(gè)原因引起申請(qǐng)不到那么多的連續(xù)內(nèi)存吧? |
|
| 3樓: | >>參與討論 |
| 作者: fanxinghua 于 2006/6/9 8:55:00 發(fā)布:
連續(xù)申請(qǐng)500個(gè)10個(gè)字節(jié)大小的內(nèi)存沒有問題 連續(xù)申請(qǐng)500個(gè)10個(gè)字節(jié)大小的內(nèi)存沒有問題 可是你在釋放的時(shí)候不是從頭到尾連續(xù)釋放的,產(chǎn)生了內(nèi)存碎片,雖然總的可用內(nèi)存還是有的,到你分配不到合適的內(nèi)存,沒有內(nèi)存整理的內(nèi)存管理是個(gè)缺陷 |
|
|
|
| 免費(fèi)注冊(cè)為維庫(kù)電子開發(fā)網(wǎng)會(huì)員,參與電子工程師社區(qū)討論,點(diǎn)此進(jìn)入 |
Copyright © 1998-2006 m.58mhw.cn 浙ICP證030469號(hào) |