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

首頁綜合 正文
目錄

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

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

http://yzkb.51969.com/

導言

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

目錄

導言

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

malloc和free

malloc

?free

calloc和realloc

calloc

?realloc

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

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

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

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

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

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

例題

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

int a;

char arr[10];

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

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

●數組在申明時,數組大小一旦確定,申請的內存空間不可變

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

malloc和free

malloc

函數參數及其返回值

void* malloc(size_t size);

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

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

注意點

●返回值是void*,那么我們在實際使用時,應把它強制轉化為我們需要的類型。

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

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

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

使用舉例:

?free

函數參數及其返回值

void free(void* ptr);

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

注意點

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

●釋放空間后,只是將權限交還于操作系統,指針還指向著地址(懸空指針),應該手動將其置為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

函數參數及其返回值

void* calloc(size_t num,size_t size);

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

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

注意點

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

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

●其他與malloc類似

使用舉例:

?realloc

?函數參數及其返回值

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

//ptr是要調整的內存地址

//size是調整之后的大小

//返回值,成功申請:返回調整空間的首地址、失?。悍祷豊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("調整前的地址:%p\n", ptr);//觀察動態(tài)(realloc)調整前的地址

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

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

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

ptr = p;

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

free(ptr);

ptr = NULL;

return 0;

}

運行結果:

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

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

注意點

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

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

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

兩種情況:

①原有地址后面有足夠的空間容納調整后的空間

②原有地址后面沒有足夠的空間容納調整后的空間

其實在前面的使用舉例中我們已經觀察到:

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

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

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

??????? 找到一塊能容納調整后的空間的地址,將數據移動到其中

關于參數size為0時的舉例:

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

?

?關于參數ptr是NULL時的情況

此時realloc等同malloc

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

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

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

?

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

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

#include

#include

int main() {

int a = 0;

int* p = &a;

free(p);

p = NULL;

return 0;

}

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

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

#include

int main() {

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

p++;

*p = 1;

free(p);

p = NULL;

return 0;

}

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

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

#include

int main() {

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

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

free(p);

p = NULL;

return 0;

}

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

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

#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;

}運行會咋樣

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

改正(二級指針):

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;

}//運行結果?

GetMemory函數返回了一個地址,但是這個地址出了函數,權限已經收回給了操作系統,str接收的是一個野指針,并將它打印出來,這種行為是未定義的,可能造成錯誤。(說到底是棧空間返回會被銷毀的問題)

我們知道只要是函數內的變量都是??臻g申請的空間,在出函數時,都會被回收,但是動態(tài)內存管理申請的空間,必須要手動釋放,所以在函數中我們使用動態(tài)內存申請的地址是不會被收回的(堆區(qū)申請),所以我們嘗試改正時,在函數內部使用動態(tà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;

}//運行結果,以及問題

沒釋放空間,內存泄漏

改正:

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;

}

使用了已經被釋放的內存

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

http://yzkb.51969.com/

推薦文章

評論可見,查看隱藏內容

本文內容根據網絡資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉載請注明,如有侵權,聯系刪除。

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

發(fā)布評論

您暫未設置收款碼

請在主題配置——文章設置里上傳

掃描二維碼手機訪問

文章目錄