網(wǎng)站首頁 編程語言 正文
一.為什么存在動態(tài)內(nèi)存分配
我們已經(jīng)掌握的內(nèi)存開辟方式有:
int a = 10;//在棧空間開辟4個字節(jié)的連續(xù)空間 int b[20] = { 0 };//在棧空間開辟20個字節(jié)的連續(xù)空間
這種開辟空間的方式有以下特點:
1.開辟空間的大小是固定的
2.開辟數(shù)組時必須指定大小
初學數(shù)組時,我寫過下面的錯誤代碼。
int N; scanf("%d",&N); int a[N]={ 0 };
可N是變量,不能用于數(shù)組元素個數(shù)的初始化。
如果我們需要的空間大小在程序運行時才能知道,那就只能試試動態(tài)內(nèi)存開辟了。
二.動態(tài)內(nèi)存函數(shù)的介紹
1.malloc和free
void* malloc (size_t size);?
void free (void* ptr);
malloc函數(shù)用于向內(nèi)存申請一塊連續(xù)可用的空間,并且返回指向這塊空間的指針。
若開辟成功,返回指向這塊空間的指針
若開辟失敗,返回NULL指針,因此malloc的返回值一定要做檢查
使用完malloc函數(shù)要用free釋放申請的內(nèi)存空間
#include<stdio.h> #include<stdlib.h> int main() { int* p = (int*)malloc(40);//開辟40個字節(jié)的棧空間 if (p == NULL) //檢查是否為空指針 { perror("malloc"); return 1; } for (int i = 0; i < 10; i++) { *(p + i)=i; } free(p); //用完后釋放空間,注意參數(shù)為首地址 p = NULL; //置為空指針 }
2.calloc
void* calloc (size_t num, size_t size)
calloc的兩個參數(shù)分別為申請元素的個數(shù)和每個元素的大小,
使用和malloc差不多,但是申請的空間會被初始化為0,
#include<stdio.h> #include<stdlib.h> int main() { int* p = (int*)calloc(10, sizeof(int)); if (p == NULL) { perror("calloc"); return 1; } for (int i = 0; i < 10; i++) { printf("%d ", *(p + i)); //輸出為 10個0 } free(p); p = NULL; }
3.realloc
void* realloc (void* ptr, size_t size)
realloc用于重新設(shè)置要開辟內(nèi)存空間的大小,可以是增大或減小
指針ptr是指向先前使用 malloc、calloc 或 realloc 分配的內(nèi)存塊的指針。
size 是新開辟內(nèi)存空間的大小
若原空間后面未開辟的空間足夠使用,則返回原先的起始地址
?若原空間后面未開辟的空間不足以填滿新開辟內(nèi)存空間,
則會在某個地址開辟所需要的空間,free掉原空間的地址,
并且返回新的地址的起始地址
真 ·? 一條龍服務(wù)
?若擴容失敗,會返回空指針,因此也要檢查是否是空指針
三.常見的動態(tài)內(nèi)存錯誤
1.對NULL指針的解引用操作
void test() { int *p = (int*)malloc(INT_MAX/4); *p = 20; free(p); }
若p為空指針,則程序錯誤。
解決方案:檢查是否為空指針
2.對動態(tài)開辟空間的越界訪問
int main() { int* p = (int*)calloc(10, sizeof(int)); if (p == NULL) { perror("calloc"); return 1; } for (int i = 0; i <= 10; i++) //當i為10時,形成越界訪問,程序出錯 { printf("%d ", *(p + i)); } free(p); p = NULL; }
使用這塊空間時要注意是否已經(jīng)越界訪問
3.對非動態(tài)開辟的空間使用free釋放
int a = 10; int* p = &a; free(p);
一執(zhí)行,程序崩潰了
4.使用free釋放一塊動態(tài)開辟空間的一部分
void test() { int* p = (int*)malloc(100); p++; free(p); }
同樣會崩潰
5.對同一塊開辟的空間多次釋放
void test() { int* p = (int*)malloc(100); free(p); free(p); }
沒錯,又又又崩潰了,就不上圖了
6.動態(tài)內(nèi)存開辟忘記釋放(內(nèi)存泄漏)
如果使用空間后不釋放,會導致內(nèi)存泄漏。
內(nèi)存泄漏的堆積,這會最終消耗盡系統(tǒng)所有的內(nèi)存。
四.幾個經(jīng)典的筆試題
第一個
void GetMemory(char* p) //對空指針解引用 { p = (char*)malloc(100); //內(nèi)存泄露 } void test() { char* str = NULL; GetMemory(str); strcpy(str, "hello world"); printf(str); } int main() { test(); }
p是str的一份臨時拷貝,指向malloc申請的起始地址,
出了函數(shù)之后,內(nèi)存還給系統(tǒng),str仍為空指針,strcpy把“hello world”放進空指針
第二個
char *GetMemory(void) { char p[] = "hello world"; return p; } void test() { char* str = NULL; str=GetMemory(); //野指針str printf(str); } int main() { test(); }
定義字符串p,并返回p的地址
但是當出了這個函數(shù),內(nèi)存還給系統(tǒng),沒有使用權(quán)限
指針變?yōu)?/p>
第三個
void GetMemory(char** p,int num) //傳址調(diào)用 { *p = (char*)malloc(num); } void test() { char* str = NULL; GetMemory(&str,100); strcpy(str, "hello world"); printf(str); //沒有free } int main() { test(); }
打印hello world
沒有釋放空間
第四個
void GetMemory(char** p,int num) { *p = (char*)malloc(num); } void test() { char* str = (char*)malloc(100); strcpy(str, "hello world"); free(str); //還給你,我還要用,哼~ if (str != NULL) { strcpy(str, "!!!"); printf(str); } } int main() { test(); }
開辟100個字節(jié)的空間后,又把這塊空間還給操作系統(tǒng)。
再次把“!!!”放進這塊空間,非法修改
tips:動態(tài)內(nèi)存管理是在堆區(qū)上進行的。
原文鏈接:https://blog.csdn.net/m0_63742310/article/details/123811337
相關(guān)推薦
- 2022-04-12 無法加載文件 ,因為在此系統(tǒng)中禁止執(zhí)行腳本。
- 2022-05-10 spring jdbctample方式訪問數(shù)據(jù)庫
- 2023-08-13 ps打開之后切圖一段時間C盤存儲量變小怎么清理?
- 2023-03-20 C#?EF去除重復列DistinctBy方式_C#教程
- 2023-06-16 GO語言中通道和sync包的使用教程分享_Golang
- 2022-11-27 搭建?Selenium+Python開發(fā)環(huán)境詳細步驟_python
- 2022-12-09 Python?hashlib模塊詳細講解使用方法_python
- 2022-11-10 C++在多線程中使用condition_variable實現(xiàn)wait_C 語言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支