網站首頁 編程語言 正文
1.動態內存管理
我們已經掌握的內存開辟方法,用的最多的就是數組,但是首先我們知道數組實在棧上開辟空間的,要是我們開辟大量的空間怎么辦呢?而且我不確定數據的大小萬一造成內存資源浪費是不是也不劃算呢?所以我認為一下兩點就很充分的說明動態開辟內存存在的必要性。
1.一般方式(棧上開辟)只能自動開辟少量的空間,但是堆上可以開辟大量的空間。
2.對于不定長數據保存問題,動態開辟空間可以解決。
2.動態開辟內存函數的介紹
2.1 malloc和free函數
C語言提供了一個動態開辟內存的函數。
void* malloc (size_t size);
C語言還提供了一個函數free是對動態開辟內存釋放和回收的。
void free (void* ptr);
這兩個函數都聲明在stdlib.h這個頭文件中
那如何進行內存的開辟與釋放呢?舉個例子。
int main() { int* p = (int*)malloc(10 * sizeof(int)); if (NULL == p) { return 1; } free(p); }
1.malloc 等空間申請都是在堆上進行申請,最后必須由free來進行釋放。堆上的空間是由程序員自己管理。
2.malloc是一個函數,表明了堆空間說在程序運行起來之后,再在系統上申請的,空間只申請不釋放,會造成內存泄露問題!
3.那free是做了什么呢?他是把開辟的空間給清除了?還是把指針給清空了?
其實都不是,free做的是取消了指針和所對應內存的指向 “關系”。
在實際申請空間的時候,真實給你的空間是要大于你所需要的,但是你只能使用你要的大小,多出來的字節,用來維護剛剛說的那種關系,以及保存該次申請的 元數據(屬性數據):用戶申請的空間有多大,所以在free傳參的時候只用傳入你開辟空間的起始地址就好了,根據屬性數據free函數就知道該釋放多少空間。
4.那我不想釋放那么多可以嗎?我按照以下代碼free。
free(p+4);
是不行的!堆空間必須整體申請整體釋放。
2.2 calloc函數
C語言還提供了一個函數calloc
void* calloc(size_t num, size_t size );
?calloc跟malloc使用基本一樣
只是有一點區別,malloc沒做初始化,隨機值,malloc效率更高一點。calloc做了初始化,效率更低一點。
2.3 relloc函數
C語言提供的這個函數讓動態內存管理更加的靈活,有時候發現申請的空間太小了,有時候覺得申請的空間太大了,合理調整內存就有了relloc函數。
void* relloc (void* ptr,size_t size);
ptr是調整內存的地址,size是調整后的大小,返回值是調整之后內存的起始地址。
一般relloc在調整內存是存在兩種情況
1.原有空間后面有足夠大的空間
直接向后擴充就好了
2.原有空間后面沒有足夠大的空間
所以說ptr也就是堆空間的起始地址有可能是變化的!
最后在分享一個題
void GetMemory(char* p) { p = (char*)malloc(100); } int main () { char* str = NULL; GetMemory(str); strcpy(str, "hello world"); printf(str); }
?這個打印的是啥呢?
其實是有錯誤的 str傳入函數發生臨時拷貝問題此時p和str不是一個東西進行動態內存開辟讓我們的p指向開辟的空間,調用函數開辟棧幀,調用完畢釋放棧幀,p是一個臨時變量于那個空間已經沒有指向關系了,而str依舊是NULL?
更改如下
void GetMemory(char** p) { *p = (char*)malloc(100); } int main() { char* str = NULL; GetMemory(&str); strcpy(str, "hello world"); printf(str); }
總結
原文鏈接:https://blog.csdn.net/qq_50119037/article/details/123097619
相關推薦
- 2022-06-23 Pandas中常用的七個時間戳處理函數使用總結_python
- 2022-12-15 uboot添加自定義命令的實現步驟_C 語言
- 2023-03-02 C++回溯算法之深度優先搜索詳細介紹_C 語言
- 2022-05-20 如何保證緩存和數據庫的一致性?
- 2023-10-16 Nginx啟動,重啟以及基本命令
- 2022-10-09 React高階組件的使用淺析_React
- 2022-04-01 本地存儲(Local Storage) 和 會話存儲(Session Storage)
- 2022-04-24 C#中的==運算符用法講解_C#教程
- 最近更新
-
- 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同步修改后的遠程分支