欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:筆記 動態(tài)內(nèi)存管理<C語言>

柚子快報邀請碼778899分享:筆記 動態(tài)內(nèi)存管理<C語言>

http://yzkb.51969.com/

導(dǎo)言

??????? 在C語言學(xué)習(xí)階段,指針、結(jié)構(gòu)體和動態(tài)內(nèi)存管理,是后期學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)的最重要的三大知識模塊,也是C語言比較難的知識模塊,但是“天下無難事”,只要認(rèn)真踏實的學(xué)習(xí),也能解決,所以下文將介紹動態(tài)內(nèi)存管理涉及到的一些函數(shù)以及概念。

目錄

導(dǎo)言

為什么存在動態(tài)內(nèi)存管理

malloc和free

malloc

?free

calloc和realloc

calloc

?realloc

常見的關(guān)于動態(tài)內(nèi)存管理錯誤

1.對可能是NULL指針的引用

?2.對不是動態(tài)開辟的內(nèi)存進(jìn)行釋放

3.對動態(tài)開辟的內(nèi)存進(jìn)行越界訪問

4.使用free釋放動態(tài)開辟內(nèi)存的一部分

5.忘記內(nèi)存釋放(忘記free),造成內(nèi)存泄漏

例題

為什么存在動態(tài)內(nèi)存管理

int a;

char arr[10];

這是我們常用的用于向內(nèi)存申請空間的辦法,但是:

●空間開辟的空間是固定的

●數(shù)組在申明時,數(shù)組大小一旦確定,申請的內(nèi)存空間不可變

在實際編寫程序時,可能我們對于內(nèi)存空間的需求不是固定,那么使用動態(tài)內(nèi)存管理自己申請空間、自己釋放空間就是一個很好的選擇。

malloc和free

malloc

函數(shù)參數(shù)及其返回值

void* malloc(size_t size);

//申請size個字節(jié)的空間

//返回值,成功申請:返回開辟空間的首地址、失?。悍祷豊ULL

注意點

●返回值是void*,那么我們在實際使用時,應(yīng)把它強(qiáng)制轉(zhuǎn)化為我們需要的類型。

●與局部變量不同,開辟空間在堆區(qū)(如數(shù)組在棧區(qū))

●malloc不會將內(nèi)存空間初始化為0,這是與最大calloc區(qū)別!

●動態(tài)內(nèi)存可調(diào)整(通過realloc)

使用舉例:

?free

函數(shù)參數(shù)及其返回值

void free(void* ptr);

//釋放動態(tài)內(nèi)存申請的ptr指向的空間

注意點

●只能用來手動釋放動態(tài)申請的空間,如果不是結(jié)果是未定義的

●釋放空間后,只是將權(quán)限交還于操作系統(tǒng),指針還指向著地址(懸空指針),應(yīng)該手動將其置為NULL

●如果釋放指針是NULL,那么什么也不做。

?使用舉例:

#include

int main() {

int* ptr = NULL;

int count = 0;

scanf("%d", &count);

ptr = (int*)malloc(count * sizeof(int));

free(ptr);

ptr = NULL;

return 0;

}

calloc和realloc

calloc

函數(shù)參數(shù)及其返回值

void* calloc(size_t num,size_t size);

//申請num個size個字節(jié)的空間,并初始化為0

//返回值,成功申請:返回開辟空間的首地址、失?。悍祷豊ULL

注意點

●開辟空間并全部初始化為0

●兩個參數(shù)(num個size字節(jié))

●其他與malloc類似

使用舉例:

?realloc

?函數(shù)參數(shù)及其返回值

void* realloc(void* ptr,size_t size);

//ptr是要調(diào)整的內(nèi)存地址

//size是調(diào)整之后的大小

//返回值,成功申請:返回調(diào)整空間的首地址、失?。悍祷豊ULL

使用舉例:

#include

#include

int main() {

int count;

scanf("%d", &count);

int* ptr = (int*)calloc(count, sizeof(int));//申請count個int大小的空間

if (ptr) {//判斷是不是NULL:是否申請成功

for (int i = 0; i < count; i++)

ptr[i] = i;//賦值:從0開始到count-1步為1的序列

for (int i = 0; i < count; i++)

printf("%d ", ptr[i]);

}

printf("\n");

printf("調(diào)整前的地址:%p\n", ptr);//觀察動態(tài)(realloc)調(diào)整前的地址

int* p = (int*)realloc(ptr, (count + 5) * sizeof(int));

//申明一個新指針來接收,防止調(diào)整失敗返回NULL,數(shù)據(jù)丟失,調(diào)整為多5個int大小的地址

if (p)//判斷是否是NULL:是否調(diào)整成功

ptr = p;

printf("調(diào)整后的地址:%p", ptr);//觀察動態(tài)(realloc)調(diào)整后的地址

free(ptr);

ptr = NULL;

return 0;

}

運(yùn)行結(jié)果:

先開辟10個int字節(jié)大小空間的運(yùn)行結(jié)果:

?先開辟20個int字節(jié)大小空間的運(yùn)行結(jié)果:

注意點

●參數(shù)size為0時,返回值是NULL,并將ptr的內(nèi)存釋放,這是未定義的行為,在不同的編譯器上不能保證

●如果ptr參數(shù)為NULL,會動態(tài)開辟一個新的內(nèi)存空間,此時realloc函數(shù)的作用等同于malloc

●這個函數(shù)調(diào)整空間時會把數(shù)據(jù)移到新的內(nèi)存空間內(nèi)(實際上,有一種情況不會,但是為了代碼的健壯性和可移植性,我們最好這樣定義)

兩種情況:

①原有地址后面有足夠的空間容納調(diào)整后的空間

②原有地址后面沒有足夠的空間容納調(diào)整后的空間

其實在前面的使用舉例中我們已經(jīng)觀察到:

先開辟10個int字節(jié)大小空間的運(yùn)行結(jié)果(第一種情況)

????????直接在原地址后面開辟新空間

先開辟20個int字節(jié)大小空間的運(yùn)行結(jié)果(第二種情況)

??????? 找到一塊能容納調(diào)整后的空間的地址,將數(shù)據(jù)移動到其中

關(guān)于參數(shù)size為0時的舉例:

因為我們沒有辦法直接觀察一塊動態(tài)開辟的內(nèi)存是否被釋放,且這種size為0行為是未定義的,所以我們只能觀察它的返回值

?

?關(guān)于參數(shù)ptr是NULL時的情況

此時realloc等同malloc

注意:動態(tài)內(nèi)存管理的4個函數(shù)都包含在

常見的關(guān)于動態(tài)內(nèi)存管理錯誤

1.對可能是NULL指針的引用

?

?2.對不是動態(tài)開辟的內(nèi)存進(jìn)行釋放

// 2.對不是動態(tài)開辟的內(nèi)存進(jìn)行釋放

#include

#include

int main() {

int a = 0;

int* p = &a;

free(p);

p = NULL;

return 0;

}

3.對動態(tài)開辟的內(nèi)存進(jìn)行越界訪問

//3.對動態(tài)開辟的內(nèi)存進(jìn)行越界訪問

#include

int main() {

int* p = (int*)malloc(sizeof(int));

p++;

*p = 1;

free(p);

p = NULL;

return 0;

}

4.使用free釋放動態(tài)開辟內(nèi)存的一部分

//4.使用free釋放動態(tài)開辟內(nèi)存的一部分

#include

int main() {

int* p = (int*)malloc(4*sizeof(int));//動態(tài)開辟4個int大小的空間

p++;//指向第二個元素

free(p);

p = NULL;

return 0;

}

5.忘記內(nèi)存釋放(忘記free),造成內(nèi)存泄漏

//5.忘記內(nèi)存釋放(忘記free),造成內(nèi)存泄漏

#include

int main() {

int* p = (int*)malloc(sizeof(int));

return 0;

}

例題

1.

void GetMemory(char* p)

{

p = (char*)malloc(100);

}

void Test(void)

{

char* str = NULL;

GetMemory(str);

strcpy(str, "hello world");

printf(str);

}

int main() {

Test();

return 0;

}運(yùn)行會咋樣

p雖然在GetMemory函數(shù)中開辟了內(nèi)存,但是在出函數(shù)時,該地址被銷毀,所以str還是NULL指針,對NULL指針進(jìn)行賦值是一個未定義行為。(傳值調(diào)用而沒有使用傳址調(diào)用)

改正(二級指針):

void GetMemory(char** p)//使用二級指針接收

{

*p = (char*)malloc(100);

}

void Test(void)

{

char* str = NULL;

GetMemory(&str);//傳入指針的地址

strcpy(str, "hello world");

printf(str);

}

int main() {

Test();

return 0;

}

改正(將開辟的空間返回):

2.

char* GetMemory(void)

{

char p[] = "hello world";

return p;

}

void Test(void)

{

char* str = NULL;

str = GetMemory();

printf(str);

}

int main() {

Test();

return 0;

}//運(yùn)行結(jié)果?

GetMemory函數(shù)返回了一個地址,但是這個地址出了函數(shù),權(quán)限已經(jīng)收回給了操作系統(tǒng),str接收的是一個野指針,并將它打印出來,這種行為是未定義的,可能造成錯誤。(說到底是??臻g返回會被銷毀的問題)

我們知道只要是函數(shù)內(nèi)的變量都是??臻g申請的空間,在出函數(shù)時,都會被回收,但是動態(tài)內(nèi)存管理申請的空間,必須要手動釋放,所以在函數(shù)中我們使用動態(tài)內(nèi)存申請的地址是不會被收回的(堆區(qū)申請),所以我們嘗試改正時,在函數(shù)內(nèi)部使用動態(tài)內(nèi)存申請,并返回。

改正:

char* GetMemory(void)

{

char* p = (char*)malloc(20);

strcpy(p, "hello world!");

return p;

}

void Test(void)

{

char* str = NULL;

str = GetMemory();

printf(str);

}

int main() {

Test();

return 0;

}

3.

//3

void GetMemory(char** p, int num)

{

*p = (char*)malloc(num);

}

void Test(void)

{

char* str = NULL;

GetMemory(&str, 100);

strcpy(str, "hello");

printf(str);

}

int main() {

Test();

return 0;

}//運(yùn)行結(jié)果,以及問題

沒釋放空間,內(nèi)存泄漏

改正:

void GetMemory(char** p, int num)

{

*p = (char*)malloc(num);

}

void Test(void)

{

char* str = NULL;

GetMemory(&str, 100);

strcpy(str, "hello");

printf(str);

free(ptr);

ptr=NULL;

}

int main() {

Test();

return 0;

}

使用了已經(jīng)被釋放的內(nèi)存

柚子快報邀請碼778899分享:筆記 動態(tài)內(nèi)存管理<C語言>

http://yzkb.51969.com/

推薦文章

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/19027170.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄