溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C語(yǔ)言中動(dòng)態(tài)內(nèi)存的示例分析

發(fā)布時(shí)間:2022-03-07 15:08:12 來(lái)源:億速云 閱讀:127 作者:小新 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要為大家展示了“C語(yǔ)言中動(dòng)態(tài)內(nèi)存的示例分析”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“C語(yǔ)言中動(dòng)態(tài)內(nèi)存的示例分析”這篇文章吧。

1.關(guān)于動(dòng)態(tài)內(nèi)存的函數(shù)

1.1 malloc和free函數(shù)

malloc這個(gè)函數(shù)向內(nèi)存申請(qǐng)一塊連續(xù)可用的空間,并返回指向這塊空間的指針,如果開(kāi)辟成功,則返回一個(gè)指向開(kāi)辟好空間的指針;如果開(kāi)辟失敗,則返回一個(gè)NULL指針,因此malloc的返回值一定要做檢查。

free函數(shù)專門(mén)是用來(lái)做動(dòng)態(tài)內(nèi)存的釋放和回收的。如果參數(shù) ptr 指向的空間不是動(dòng)態(tài)開(kāi)辟的,那free函數(shù)的行為是未定義的;如果參數(shù) ptr 是NULL指針,則函數(shù)什么事都不做。
 

C語(yǔ)言中動(dòng)態(tài)內(nèi)存的示例分析

C語(yǔ)言中動(dòng)態(tài)內(nèi)存的示例分析

說(shuō)明:

該函數(shù)設(shè)計(jì)的巧妙的一點(diǎn)就是返回值為void*,因?yàn)楹瘮?shù)創(chuàng)造者并不知道使用者是想以什么樣的類型指針來(lái)接收動(dòng)態(tài)開(kāi)辟的空間,所以使用者在使用時(shí)只需要強(qiáng)行轉(zhuǎn)換成自己想要的類型就可以:

int* p = (int*)malloc(40);//假設(shè)是整型時(shí)的例子

在使用完動(dòng)態(tài)開(kāi)辟的空間后記得要用free函數(shù)向操作系統(tǒng)釋放開(kāi)辟的空間,并且將指針賦為空指針:

int* p = (int*)malloc(40);
 
//......
 
free(p);//避免內(nèi)存泄漏
p = NULL;//原指針指向的位置既然已經(jīng)還給操作系統(tǒng)的,就將指針賦為空指針,避免野指針等問(wèn)題

 如果參數(shù) size 為0,malloc的行為是標(biāo)準(zhǔn)是未定義的,取決于編譯器。

需要引頭文件stdlib.h

1.2 calloc函數(shù)

C語(yǔ)言中動(dòng)態(tài)內(nèi)存的示例分析

 calloc可與malloc函數(shù)相對(duì)照來(lái)學(xué)習(xí),calloc函數(shù)的功能是為 num 個(gè)大小為 size 的元素開(kāi)辟一塊空間,并且把空間的每個(gè)字節(jié)初始化為0。與malloc有兩點(diǎn)不同:

參數(shù)不同,calloc需要指明開(kāi)辟空間的數(shù)據(jù)類型和該類型數(shù)據(jù)的個(gè)數(shù),而malloc是全部字節(jié)數(shù);

calloc在開(kāi)辟空間的同時(shí)將空間內(nèi)的全部字節(jié)初始化為0.

C語(yǔ)言中動(dòng)態(tài)內(nèi)存的示例分析

1.3 realloc函數(shù)

C語(yǔ)言中動(dòng)態(tài)內(nèi)存的示例分析

 realloc函數(shù)用來(lái)調(diào)整開(kāi)辟空間的大小,有時(shí)可能開(kāi)辟的空間小了,有時(shí)候可能開(kāi)辟的大了,都可以通過(guò)realloc函數(shù)來(lái)修改,并且會(huì)將原來(lái)內(nèi)存中的數(shù)據(jù)移動(dòng)到新的空間。

realloc在調(diào)整空間大小時(shí)有兩種情況:

原有空間后有足夠大的空間,這種情況下擴(kuò)展內(nèi)存就直接原有內(nèi)存之后直接追加空間,原來(lái)空間的數(shù)據(jù)不發(fā)生變化,返回值為原來(lái)位置的指針;

C語(yǔ)言中動(dòng)態(tài)內(nèi)存的示例分析

 2.原有空間后沒(méi)有足夠大的空間,這時(shí)便在堆空間找到大小合適的連續(xù)空間使用,并將原有空間的數(shù)據(jù)轉(zhuǎn)移到新的空間返回值為新空間的地址。

C語(yǔ)言中動(dòng)態(tài)內(nèi)存的示例分析

int main()
{
    int *str = (int*)malloc(10);
    if(str != NULL)
{
    //.....
}
else
{
    exit(EXIT_FAILURE);
}
    //擴(kuò)展容量
//代碼1
str = (int*)realloc(str, 1000);//這樣可以嗎?(如果申請(qǐng)失敗會(huì)返回一個(gè)空指針?。。?
 
 
//修改代碼2
int*p = NULL;
p = realloc(str, 1000);
if(p != NULL)
{
    str = p;
}
//...
free(str);
return 0;
}

2.常見(jiàn)的動(dòng)態(tài)內(nèi)存錯(cuò)誤

2.1 對(duì)NULL指針解引用

int* p = (int*)malloc(40);
*p=10;
free(p);

這就是忽略了返回值可能是空指針的可能,如果開(kāi)辟失敗會(huì)返回空指針。所以最好的做法就是判斷一下指針是否為空,然后再進(jìn)行下一步。

int* p = (int*)malloc(40);
if(p != NULL)
{
    *p=10;
}
free(p);

2.2 對(duì)動(dòng)態(tài)內(nèi)存開(kāi)辟的空間越界訪問(wèn)

就類似于使用數(shù)組時(shí)對(duì)數(shù)組越界訪問(wèn)。

int i = 0;
int *p = (int *)malloc(10*sizeof(int));
if(NULL == p)
{
    exit(EXIT_FAILURE);
}
for(i=0; i<=10; i++)
{
    *(p+i) = i;//當(dāng)i是10的時(shí)候越界訪問(wèn)
}
free(p);

2.3 對(duì)非動(dòng)態(tài)開(kāi)辟內(nèi)存使用free釋放

int a = 0;
int* p = &a;
free(p);

通過(guò)查閱MSDN可以發(fā)現(xiàn):Attempting to free an invalid pointer (a pointer to a memory block that was not allocated by calloc, malloc, or realloc) may affect subsequent allocation requests and cause errors. 就是說(shuō)如果用free釋放非calloc,malloc,realloc函數(shù)動(dòng)態(tài)開(kāi)辟的空間可能會(huì)導(dǎo)致后續(xù)的分配請(qǐng)求并且導(dǎo)致錯(cuò)誤。

2.4 使用free釋放一塊動(dòng)態(tài)開(kāi)辟內(nèi)存的一部分

int *p = (int *)malloc(100);
p++;
free(p);//p不再指向動(dòng)態(tài)內(nèi)存的起始位置

會(huì)導(dǎo)致動(dòng)態(tài)開(kāi)辟的空間無(wú)法完全釋放,進(jìn)而可能會(huì)導(dǎo)致內(nèi)存泄漏。

2.5 對(duì)同一塊動(dòng)態(tài)內(nèi)存多次釋放

int *p = (int *)malloc(10);
free(p);
free(p);//重復(fù)釋放

2.6 內(nèi)存泄漏

void test()
{
    int *p = (int *)malloc(100);
    if(NULL != p)
    {
        *p = 20;
    }
}
int main()
{
    test();
    return 0;
}

如果使用完動(dòng)態(tài)內(nèi)存又不釋放則會(huì)導(dǎo)致這塊內(nèi)存無(wú)法在后續(xù)被利用,導(dǎo)致內(nèi)存泄漏。動(dòng)態(tài)開(kāi)辟的空間一定要釋放,并且正確釋放。

補(bǔ)充:為什么要引入動(dòng)態(tài)內(nèi)存分配

1.指針只能指向一個(gè)確切的內(nèi)存空間,欲使用一個(gè)數(shù)據(jù),必須先設(shè)定一個(gè)變量來(lái)保存它么?

2.在程序設(shè)計(jì)時(shí),數(shù)據(jù)多為動(dòng)態(tài)的。即程序運(yùn)行時(shí)數(shù)據(jù)項(xiàng)的數(shù)量是變化的。

3.用數(shù)組保存多個(gè)元素時(shí),很難預(yù)知實(shí)際運(yùn)行時(shí)存儲(chǔ)的元素個(gè)數(shù),往往會(huì)導(dǎo)致預(yù)定義的元素個(gè)數(shù)不足或過(guò)多

例如:電話簿的管理程序。當(dāng)添加新聯(lián)系人時(shí),數(shù)據(jù)項(xiàng)將增加;刪除聯(lián)系人時(shí),數(shù)據(jù)項(xiàng)將減少。

動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)可以在運(yùn)行時(shí)靈活地添加、刪除或重排數(shù)據(jù)項(xiàng)。
動(dòng)態(tài)內(nèi)存管理可以在運(yùn)行時(shí)分配更多的內(nèi)存空間或釋放掉不再需要的空間,因而可以優(yōu)化存儲(chǔ)空間的使用。

所以&mdash;&mdash;&mdash;由于無(wú)法預(yù)知在運(yùn)行時(shí)數(shù)組元素的使用情況,在程序中預(yù)定義的數(shù)組大小,如果過(guò)小,會(huì)導(dǎo)致程序運(yùn)行失??;如果過(guò)大,則會(huì)浪費(fèi)內(nèi)存空間。

如果在運(yùn)行時(shí)根據(jù)實(shí)際需要來(lái)決定內(nèi)存的使用情況,則可以很好的解決以上問(wèn)題。

以上是“C語(yǔ)言中動(dòng)態(tài)內(nèi)存的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI