日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言-动态内存管理

發布時間:2023/12/18 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言-动态内存管理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C語言中,我們在使用數組的時候,經常有這樣的一個問題:數組在申明的時候,必須指定數組的長度,它所需要的內存在編譯時分配。有的時候,我們開辟的空間太小,無法滿足我們的需求,有時又太大,浪費空間比較嚴重。那么能不能按照需求,需要一個就開辟一個空間,需要兩個就開辟兩個空間? 這時候就只能試試動態內存開辟了。

一、malloc 函數和free 函數

C語言提供了一個用來動態開辟的函數:malloc函數。頭文件是stdlib.h。

void* malloc (size_t size);

該函數能夠在內存中申請一塊連續可用的空間,如果開辟成功,就返回這個開辟好空間的指針,否則,就返回NULL。因此,在使用malloc的時候,一定要對函數的返回值做檢查,避免空指針引用。由于malloc函數不知道要開辟的空間是什么類型,所以在使用的時候,一般要進行強制類型轉換。

free 函數是用來進行動態內存的釋放和回收的。頭文件是stdlib.h。

void free (void* ptr);

free函數只能對動態內存的函數進行釋放。如果不是指向的空間不是動態開辟的,那么free函數的結果都是未定義的。

#include<stdio.h>
#include<stdlib.h>
?
int main(void)
{
?? ?int* a = (int*)malloc(sizeof(int));//給a動態開辟空間
?? ?
?? ?free(a);
? ? a = NULL;
?? ?return 0;
}

?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?給a申請空間

?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?free(a)
?上面的例子只是單純的說明malloc函數的用法。要注意的是,一般情況下,一定要對malloc函數的返回值做檢查,同時,在使用完成malloc函數之后,要及時的進行釋放。同時,對引用的指針賦值為空。否則,上面的a就成為了野指針,在后面再次使用的時候就會導致出現非法訪問的問題。

二、calloc 函數

calloc 函數的功能是為 num 個大小為 size 的元素開辟一塊空間,并且把空間的每個字節初始化為0。與函數 malloc 的區別只在于 calloc 會在返回地址之前把申請的空間的每個字節初始化為全0。

void* calloc (size_t num, size_t size);

#include<stdio.h>
#include<stdlib.h>
?
int main(void)
{
?? ?int* p = (int*)calloc(10, sizeof(int));//給p動態開辟空間
?
?? ?free(p);
?? ?return 0;
}


三、realloc 函數

?

有的時候我們使用malloc函數之后,發現申請的空間還是太小,有的時候太大,想要再次進行修改,這個時候就可以使用realloc函數。頭文件是stdlib.h。

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

?ptr 是要調整的內存地址,size 是調整之后新大小。返回值是調整之后的內存的起始位置。

?

realloc函數進行調整的時候,有以下方式:

1,如果原有空間后面有足夠大的空間,就直接擴展。

2,另找一塊滿足要求的空間將原有空間的值進行拷貝,同時返回新的空間地址。

realloc函數的返回結果在使用時也要進行返回值是否為NULL的判斷。?

?

?四、常見的內存錯誤

1,對NULL指針解引用操作

#include<stdio.h>
#include<stdlib.h>
?
void test()
{
?? ?int* p = (int*)malloc(INT_MAX / 4);
?? ?if (p != NULL)
?? ?{
?? ??? ?*p = 20;//如果p的值是NULL,就會有問題,要進行判斷
?? ??? ?printf("%d", *p);//20
?? ?}
?? ?else
?? ?{
?? ??? ?printf("為空!");
?? ?}
?
?? ?free(p);
}
?
int main(void)
{
?? ?test();
?? ?return 0;
}
2,對動態開辟的空間越界訪問

void test()
{
?? ?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;//當i是10的時候越界訪問
?? ?}
?? ?free(p);
}
?
?
int main(void)
{
?? ?test();
?? ?return 0;
}
程序就會崩潰。

?

3,對非動態開辟的空間進行free釋放

void test()
{
?? ?int a = 10;
?? ?int* p = &a;
?? ?free(p);
}
?
int main(void)
{
?? ?test();
?
?? ?return 0;
}

?

?4,只釋放動態開辟內存的一部分

void test()
{
?? ?int* p = (int*)malloc(100);
?? ?p++;
?? ?free(p);//p不再指向動態內存的起始位置
}
?
int main(void)
{
?? ?test();
?
?? ?return 0;
}
結果同上。

5,多次釋放同一塊內存。

void test()
{
?? ?int* p = (int*)malloc(100);
?? ?free(p);
?? ?free(p);//重復釋放
}
?
int main(void)
{
?? ?test();
?
?? ?return 0;
}
還是同樣的結果。

6,忘記釋放,造成內存泄露。

void test()
{
?? ?int* p = (int*)malloc(100);
?? ?if (NULL != p)
?? ?{
?? ??? ?*p = 20;
?? ?}
}
int main()
{
?? ?test();
?? ?while (1);
}
動態內存的開辟是在堆上開辟的,這里面的內存需要自己手動來進行釋放,如果不釋放,在最后程序結束的時候可能由系統自動回收。

我們平時寫的變量等在棧,數據段(存放全局變量,靜態變量)等中,這些不需要手動釋放,他們有自己的作用域,出了這個作用域就會自動被銷毀。而在堆上開辟的空間需要手動來釋放。
?

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的C语言-动态内存管理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。