網站首頁 編程語言 正文
1. 為什么存在動態內存分配
*動態內存開辟在堆區*
我們已經掌握的開辟內存方式是類型直接定義變量,開辟的內存是固定的,像:
int a=20; //在棧空間上開辟四個字節
還有數組,我們可以指定開辟空間的大小,像:
char arr[10] = {0}; ///在棧空間上開辟10個字節的連續空間
但在程序運行時,很多時候我們會遇到內存不夠或者內存過多引起的浪費問題,那么有沒有那種使用多少內存開辟多少內存的方法?這就是本篇文章要介紹的動態內存。
2. 動態內存函數的介紹
2.1 malloc和free
malloc和free都聲明在 stdlib.h 頭文件中
void* malloc (size_t size); //向內存申請一塊連續可用的空間,并返回指向這塊空間的指針
如果開辟成功,則返回一個指向開辟好空間的指針。 如果開辟失敗,則返回一個NULL指針。 返回值的類型是 void* ,malloc函數并不知道開辟空間的類型,在使用的時候自己來決定。
void free (void* ptr); //free函數用來釋放動態開辟的內存
如果參數 ptr 指向的空間不是動態開辟的,那free函數的行為是未定義的。
如果參數 ptr 是NULL指針,則函數什么事都不做。
舉例:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> int main() { //開辟10個整型空間 int* p = (int*)malloc(40); if (NULL==p) { printf("%s\n",strerror(errno)); //判斷開辟失敗的原因 return 0; } //使用 //釋放 free(p); //將空間還給系統,但是里面的內容沒有改變,還可以通過p來找到地址 p = NULL; //因此要將地址置為空指針 return 0; }
2.2 calloc?
void* calloc (size_t num, size_t size); //num為元素個數,size為每個元素的大小
注:與函數 malloc 的區別只在于 calloc 會在返回地址之前把申請的空間的每個字節初始化為全0
當用calloc來開辟10個整型空間時
int* p = (int*)calloc(10,sizeof(int));
2.3 realloc
void* realloc (void* ptr, size_t size); //ptr 是要調整的內存地址 size 調整之后新大小 //返回值為調整之后的內存起始位置
realloc在調整內存空間的是存在兩種情況:
1.當原地址后有足夠的空間時,可以接著原地址連續開辟空間,最后返回起始地址。
2.當原地址后空間不足以開辟我們所需要的空間時,那么realloc會自動尋找一塊足以存放我們需要的的空間,并將原地址的內容復制到新空間中,釋放掉原地址中的內容,返回開辟出空間的初始地址。
我們可以先判斷是否開辟成功,再將地址賦予p
3. 常見的動態內存錯誤
3.1 對NULL指針的解引用操作
開辟動態內存時,一定要注意對返回空指針的函數要進行判斷,防止對空指針進行解引用,以免程序出現問題。
3.2 對動態開辟空間的越界訪問
int *p = (int *)malloc(10*sizeof(int)); //開辟內存 if(NULL == p) //判斷是否開辟成功 { exit(EXIT_FAILURE); } int i=0; for(i=0; i<=10; i++) { *(p+i) = i;//當i是10的時候越界訪問 } free(p);
這塊可以像理解數組一樣,不能訪問下標為10的地址,會造成越界訪問。
3.3 對非動態開辟內存使用free釋放
void test() { int a = 10; int *p = &a; free(p); } int main() { test(); return 0; }
不是動態內存開辟的空間內存不在堆區,沒必要用free釋放,在棧區開辟的空間在出了作用域后會自動還給系統,沒有必要,也不允許用free進行釋放。
3.4 使用free釋放一塊動態開辟內存的一部分
void test() { int *p = (int *)malloc(100); p++; free(p);//p不再指向動態內存的起始位置 }
?不支持釋放一部分內存,這樣的寫法不支持不可取。只能從動態內存開辟的起始位置來進行釋放。
3.5 對同一塊動態內存多次釋放
void test() { int *p = (int *)malloc(100); free(p); free(p);//重復釋放 }
重復釋放也會報錯
當p第一次釋放后,將p=NULL,再次釋放的話就不會有問題;寫代碼是要避免重復釋放的情況,同時要記住每次釋放完之后都要將地址置為空指針。
若忘記釋放開辟的空間,就會造成內存泄漏的問題(在釋放該段內存之前就失去了對該段內存的控制,從而造成了內存的浪費)
原文鏈接:https://blog.csdn.net/weixin_53316121/article/details/122748819
- 上一篇:合并兩個遞增有序的單鏈表,使合并后仍遞增有序
- 下一篇:算法時間復雜度和空間復雜度
相關推薦
- 2022-01-12 修改node_modules的包
- 2022-01-28 laravel try異常abort只報出最外層
- 2021-09-09 Linux下NTP服務器配置詳細過程_Linux
- 2022-05-27 一起來看看python的裝飾器代碼_python
- 2022-06-09 Redis超詳細講解高可用主從復制基礎與哨兵模式方案_Redis
- 2022-04-28 C#圖形編程GDI+基礎介紹_C#教程
- 2022-10-08 Python中集合創建與使用詳解_python
- 2023-01-26 python獲取redis?memory使用情況場景分析_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支