您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)C語(yǔ)言的動(dòng)態(tài)內(nèi)存管理是什么意思,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
(1)用malloc類的函數(shù)分配內(nèi)存;
(2)用這些內(nèi)存支持應(yīng)用程序;
(3)用free函數(shù)釋放內(nèi)存。
內(nèi)存的簡(jiǎn)答來說的三大操作:分配----使用----釋放
內(nèi)存管理指的是:分配— ----釋放
我們編寫的程序代碼:使用
程序本質(zhì)上就是處理數(shù)據(jù),數(shù)據(jù)信息需要存放在內(nèi)存里,就是用二極管表示的開斷表示二進(jìn)制數(shù),進(jìn)一步用二進(jìn)制數(shù)表示萬(wàn)物:如音樂、文字、視頻、圖片、等等各種資源。
分配–釋放:為了更好的利用和回收內(nèi)存資源,最大程度的發(fā)揮計(jì)算資源,統(tǒng)一操作系統(tǒng)來調(diào)度
動(dòng)態(tài)內(nèi)存分配其實(shí)就要談到自動(dòng)內(nèi)存分配
自動(dòng)分配:內(nèi)存其實(shí)就是我們?cè)诰幊涛募锒x的變量實(shí)際在運(yùn)行時(shí)映射的內(nèi)存,這部分變量的內(nèi)存都是由系統(tǒng)自動(dòng)管理(分配-釋放)。函數(shù)體(或者語(yǔ)句塊)內(nèi)的變量都是分布在函數(shù) 幀 里面,運(yùn)行時(shí)就會(huì)把這個(gè)幀插入到函數(shù)運(yùn)行棧里,內(nèi)存這些都由系統(tǒng)分撥,運(yùn)行完就出棧,內(nèi)存也被操作系統(tǒng)回收,一致到主函數(shù)出棧,程序退出。
動(dòng)態(tài)分配:就是我們自己手動(dòng)申請(qǐng)操作系統(tǒng)給我們程序分配的內(nèi)存,內(nèi)存區(qū)域主要在于 堆 上,這部分資源是我們手動(dòng)申請(qǐng)和回收的。分配到的資源是我們來操作、存放數(shù)據(jù)的地方。
實(shí)際上我們定義的變量最后也會(huì)被翻譯為地址,都是通過尋址來操作變量的值(可以去看看匯編語(yǔ)言)
#include <stdio.h> #include <stdlib.h> int main(void) { int*pi=(int*)malloc(sizeof(int)); *pi=5; printf("*pi:%d\n",*pi); free(pi); return 0; }
注意點(diǎn)
int *pi=(int)malloc((4));
然而,依賴于系統(tǒng)所用的內(nèi)存模型,整數(shù)的長(zhǎng)度可能會(huì)發(fā)生變化??梢浦驳姆椒ㄊ鞘褂胹izeof操作符,這樣不管程序在哪里運(yùn)行都會(huì)返回正確的長(zhǎng)度。
使用(int)malloc(number * (sizeof(int)));*
有幾個(gè)內(nèi)存分配函數(shù)可以用來管理動(dòng)態(tài)內(nèi)存,雖然具體可用的函數(shù)取決于系統(tǒng),但大部分系統(tǒng)的stdlib.h頭文件中都有如下函數(shù):
malloc()
realloc()
calloc()
函數(shù) | 描述 |
---|---|
malloc | 從堆上分配內(nèi)存 |
realloc | 在之前分配的內(nèi)存塊的基礎(chǔ)上,將內(nèi)存重新分配為更大或者更小的部分 |
calloc | 從堆上分配內(nèi)存并清零 |
malloc函數(shù)從堆上分配一塊內(nèi)存,所分配的字節(jié)數(shù)由該函數(shù)唯一的參數(shù)指定,返回值是void指針,如果內(nèi)存不足,就會(huì)返回NULL。此函數(shù)不會(huì)清空或者修改內(nèi)存。
聲明:void* malloc(size_t);
(1)從堆上分配內(nèi)存;
(2)內(nèi)存不會(huì)被修改或是清空;
(3)返回首字節(jié)的地址。
實(shí)例用法:int* pi=(int*)malloc(sizeof(int));
因?yàn)楫?dāng)malloc無法分配內(nèi)存時(shí)會(huì)返回NULL,在使用它返回的指針之前先檢查NULL是不錯(cuò)的做法,如下所示:
int*pi=(int*)malloc(sizeof(int)); if(pi!=NULL) { //指針沒有問題 }else { //無效的指針 }
(4)靜態(tài)、全局指針和malloc
初始化靜態(tài)或全局變量時(shí)不能調(diào)用函數(shù)。下面的代碼聲明一個(gè)靜態(tài)變量,并試圖用malloc來初始化:
*static int pi = malloc(sizeof(int));
這樣會(huì)產(chǎn)生一個(gè)編譯時(shí)錯(cuò)誤消息,全局變量也一樣。
對(duì)于靜態(tài)變量,可以通過在后面用一個(gè)單獨(dú)的語(yǔ)句給變量分配內(nèi)存來避免這個(gè)問題。但是全局變量不能用單獨(dú)的賦值語(yǔ)句,因?yàn)槿肿兞渴窃诤瘮?shù)和可執(zhí)行代碼外部聲明的,賦值語(yǔ)句這類代碼必須出現(xiàn)在函數(shù)中:
static int *pi;
pi = malloc(sizeof(int));
聲明:void *realloc(void *ptr,size t size);
realloc函數(shù)返回指向內(nèi)存塊的指針。該函數(shù)接受兩個(gè)參數(shù),第一個(gè)參數(shù)是指向原內(nèi)存塊的指針,第二個(gè)是請(qǐng)求的大小。重新分配的塊大小和第一個(gè)參數(shù)引用的塊大小不同。返回值是指向重新分配的內(nèi)存的指針。
第一個(gè)參數(shù) | 第二個(gè)參數(shù) | 行為 |
---|---|---|
空 | 無 | 同malloc |
非空 | 0 | 原內(nèi)存塊被釋放 |
非空 | 比原內(nèi)存塊小 | 利用當(dāng)前的塊分配更小的塊 |
非空 | 比原內(nèi)存塊大 | 要么在當(dāng)前位置要么在其他位置分配更大的塊 |
堆管理器可以重用原始的內(nèi)存塊,且不會(huì)修改其內(nèi)容。不過程序繼續(xù)使用的內(nèi)存超過了所請(qǐng)求的8字節(jié)。也就是說,我們沒有修改字符串以便它能裝進(jìn)8字節(jié)的內(nèi)存塊中。在本例中,我們本應(yīng)該調(diào)整字符串的長(zhǎng)度以使它能裝進(jìn)重新分配的8字節(jié)。實(shí)現(xiàn)這一點(diǎn)最簡(jiǎn)單的辦法是將NUL賦給地址507。實(shí)際使用的內(nèi)存超出分配的內(nèi)存不是個(gè)好做法,應(yīng)該避免。
calloc函數(shù)在申請(qǐng)內(nèi)存時(shí)會(huì)清空內(nèi)存【清空內(nèi)存的意思是將其內(nèi)容置為二進(jìn)制0】
聲明: void *calloc(size_t numElements,size_t elementSize);
calloc函數(shù)會(huì)根據(jù)numElements和elementSize兩個(gè)參數(shù)的乘積來分配內(nèi)存,并返回一個(gè)指向內(nèi)存的第一個(gè)字節(jié)的指針。如果不能分配內(nèi)存,則會(huì)返回NULL。此函數(shù)最初用來輔助分配數(shù)組內(nèi)存。
如果numElements或elementSize為0,那么calloc可能返回空指針。如果calloc無法分配內(nèi)存就會(huì)返回空指針,而且全局變量errno會(huì)設(shè)置為ENOMEM(內(nèi)存不足),這是POSIX錯(cuò)誤碼,有的系統(tǒng)上可能沒有。
有了動(dòng)態(tài)內(nèi)存分配,程序員可以將不再使用的內(nèi)存返還給系統(tǒng),這樣可以釋放內(nèi)存
留作他用。通常用free函數(shù)實(shí)現(xiàn)這一點(diǎn),該函數(shù)的原型如下:
聲明: void free(void *ptr);
指針參數(shù)應(yīng)該指向由malloc類函數(shù)分配的內(nèi)存的地址,這塊內(nèi)存會(huì)被返還給堆。盡管指針仍然指向這塊區(qū)域,但是我們應(yīng)該將它看成指向垃圾數(shù)據(jù)。稍后可能重新分配這塊區(qū)域,并將其裝進(jìn)不同的數(shù)據(jù)。
要點(diǎn)
釋放含義:指的是釋放堆上的申請(qǐng)內(nèi)存,其實(shí)就是告訴堆管理器,這個(gè)資源我不用了,可以回收了
但本地還是保留了之前申請(qǐng)內(nèi)存的地址,這個(gè)地址我們應(yīng)該避免去使用,也就是置這個(gè)指針為NULL
不能再去接引已釋放資源指針的值
不能重復(fù)多次釋放指針指向的內(nèi)存(free)
如果內(nèi)存已經(jīng)釋放,而指針還在引用原始內(nèi)存,這樣的指針就稱為迷途指針。迷途指針沒有指向有效對(duì)象,有時(shí)候也稱為過早釋放。
迷途指針帶來的問題:
如果訪問內(nèi)存,則行為不可預(yù)期;
如果內(nèi)存不可訪問,則是段錯(cuò)誤;
潛在的安全隱患。
造成的原因:
訪問已釋放的內(nèi)存;
返回的指針指向的是上次函數(shù)調(diào)用中的自動(dòng)變量;
//第一種情況 int*pi = (int*)malloc(sizeof(int)); printf("*pi:%d\n",*pi); free(pi); *pi = 10; //第二種情況 int*p1 = (int*)malloc(sizeof(int)); *p1 = 5; int* p2; p2 = p1; free(p1); *p2 = 10;//迷途指針 //第三種情況 /* 大部分編譯器都把塊語(yǔ)句當(dāng)做一個(gè)棧幀。tmp變量分配在棧幀上,之后在塊語(yǔ)句退出時(shí)會(huì)出棧。 pi指針現(xiàn)在指向一塊最終可能被其他活躍記錄(比如foo函數(shù))覆蓋的內(nèi)存區(qū)域。 圖2-13說明的就是這種情形。 */ int *pi; int tmp = 5; pi = &tmp; //這里pi變成了迷途指針 foo();
關(guān)于“C語(yǔ)言的動(dòng)態(tài)內(nèi)存管理是什么意思”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。