C/C++內存管理及內存泄漏詳解

?

目錄

C/C++內存分布

?C語言中動態內存管理方式:malloc/calloc/realloc/free

C++內存管理方式

new/delete操作內置類型

new和delete操作自定義類型

operator new與operator delete函數

?new和delete的實現原理

內置類型

自定義類型

內存泄漏

概念

內存泄漏分類



?C/C++內存分布

先來看看下面一段代碼和相關問題

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{static int staticVar = 1;int localVar = 1;int num1[10] = { 1, 2, 3, 4 };char char2[] = "abcd";const char* pChar3 = "abcd";int* ptr1 = (int*)malloc(sizeof(int) * 4);int* ptr2 = (int*)calloc(4, sizeof(int));int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);free(ptr1);free(ptr3);
}

?這些問題就涉及到C/C++程序的內存分布問題

  1. 棧區(stack):在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。棧區主要存放運行函數而分配的局部變量、函數參數、返回數據、返回地址等。
  2. 堆區(heap):?般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS(操作系統)回收。分配方式類似于鏈表。
  3. 數據段(靜態區)(static):存放全局變量、靜態數據。程序結束后由系統釋放。
  4. 代碼段:存放函數體(類成員函數和全局函數)的二進制代碼(可執行的代碼/只讀常量
    )。
  5. 內存映射段 是高效的I/O映射方式,用于裝載一個共享的動態內存庫。用戶可使用系統接口
    創建共享共享內存,做進程間通信。
    ?

??C語言中動態內存管理方式:malloc/calloc/realloc/free

void Test()
{int* p1 = (int*)malloc(sizeof(int));free(p1);int* p2 = (int*)calloc(4, sizeof(int));int* p3 = (int*)realloc(p2, sizeof(int) * 10);free(p3);
}
  • malloc:這個函數向內存申請?塊連續可用的空間,并返回指向這塊空間的指針。參數 size 指的是申請的空間的大小
  • calloc:函數的功能是為 num 個大小為 size 的元素開辟?塊空間,并且把空間的每個字節初始化為0。
  • realloc:realloc 函數可以對動態開辟內存大小進行調整,返回值為調整之后的內存起始位置。
  • free:free函數用來釋放動態開辟的內存。

?C++內存管理方式

C語言內存管理方式在C++中可以繼續使用,但有些地方就無能為力,而且使用起來比較麻煩,因此C++又提出了自己的內存管理方式:通過new和delete操作符進行動態內存管理。

?new/delete操作內置類型

void Test()
{// 動態申請一個int類型的空間int* ptr4 = new int;// 動態申請一個int類型的空間并初始化為10int* ptr5 = new int(10);// 動態申請10個int類型的空間int* ptr6 = new int[3];delete ptr4;delete ptr5;delete[] ptr6;
}

?new返回的是該數據類型的指針

注意:申請和釋放單個元素的空間,使用new和delete操作符,申請和釋放連續的空間,使用
new[]和delete[],注意:匹配起來使用。

?new和delete操作自定義類型

new/delete 和 malloc/free最大區別是 new/delete對于【自定義類型】除了開空間還會調用構造函數和析構函數

class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};
int main()
{// new/delete 和 malloc/free最大區別是 new/delete對于【自定義類型】除了開空間還會調用構造函數和析構函數A* p1 = (A*)malloc(sizeof(A));A* p2 = new A(1);free(p1);delete p2;// 內置類型是幾乎是一樣的int* p3 = (int*)malloc(sizeof(int)); // Cint* p4 = new int;free(p3);delete p4;A* p5 = (A*)malloc(sizeof(A) * 10);A* p6 = new A[10];free(p5);delete[] p6;return 0;
}

?new和malloc時的對比:

delete和free的對比:

注意:在申請自定義類型的空間時,new會調用構造函數,delete會調用析構函數,而malloc與
free不會。

我們在使用malloc時,常常需要進行如下的類型檢查,防止內存開辟失敗:

struct Node
{int val;Node* next;
};
//以創建一個鏈表的節點為例
Node* CreateNode(int val)
{Node* newnode = (Node*)malloc(sizeof(Node));if (newnode = NULL){perror("malloc!");exit(-1);}newnode->val = val;newnode->next = NULL;return newnode;
}

?而在C++中,我們使用new進行開辟空間時,不需要進行這樣的手動檢查,new在開辟失敗時,會拋異常。

?operator new與operator delete函數

new和delete是用戶進行動態內存申請和釋放的操作符operator new 和operator delete
系統提供的全局函數new在底層調用operator new全局函數來申請空間delete在底層通過
operator delete全局函數來釋放空間。

operator new:該函數實際通過malloc來申請空間,當malloc申請空間成功時直接返回;申請空間
失敗,嘗試執行空間不足應對措施,如果改應對措施用戶設置了,則繼續申請,否則拋異常。

void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{// try to allocate size bytesvoid* p;while ((p = malloc(size)) == 0)if (_callnewh(size) == 0){// report no memory// 如果申請內存失敗了,這里會拋出bad_alloc 類型異常static const std::bad_alloc nomem;_RAISE(nomem);}return (p);
}

operator delete: 該函數最終是通過free來釋放空間的

void operator delete(void *pUserData)
{
_CrtMemBlockHeader * pHead;
RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
if (pUserData == NULL)
return;
_mlock(_HEAP_LOCK); /* block other threads */
__TRY
/* get a pointer to memory block header */
pHead = pHdr(pUserData);
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
_free_dbg( pUserData, pHead->nBlockUse );
__FINALLY
_munlock(_HEAP_LOCK); /* release other threads */
__END_TRY_FINALLY
return;
}/*
free的實現
*/
#define free(p) _free_dbg(p, _NORMAL_BLOCK)

通過上述兩個全局函數的實現知道,operator new 實際也是通過malloc來申請空間,如果
malloc申請空間成功就直接返回,否則執行用戶提供的空間不足應對措施,如果用戶提供該措施
就繼續申請,否則就拋異常。operator delete 最終是通過free來釋放空間的。
?

??new和delete的實現原理

?內置類型

如果申請的是內置類型的空間,new和malloc,delete和free基本類似,不同的地方是:
new/delete申請和釋放的是單個元素的空間,new[] 和 delete[] 申請的是連續空間,而且new在申請空間失敗時會拋異常,malloc會返回NULL。

?自定義類型

new的原理

  1. 1. 調用operator new函數申請空間
  2. 2. 在申請的空間上執行構造函數,完成對象的構造

delete的原理

  1. 在空間上執行析構函數,完成對象中資源的清理工作
  2. 調用operator delete函數釋放對象的空間

new T[N]的原理

  1. 調用operator new[]函數,在operator new[]中實際調用operator new函數完成N個對象空間的申請
  2. 在申請的空間上執行N次構造函數

delete[]的原理

  1. 在釋放的對象空間上執行N次析構函數,完成N個對象中資源的清理
  2. 調用operator delete[]釋放空間,實際在operator delete[]中調用operator delete來釋放空間

?內存泄漏

?概念

什么是內存泄漏:內存泄漏指因為疏忽或錯誤造成程序未能釋放已經不再使用的內存的情況。內
存泄漏并不是指內存在物理上的消失,而是應用程序分配某段內存后,因為設計錯誤,失去了對
該段內存的控制,因而造成了內存的浪費。
內存泄漏的危害:長期運行的程序出現內存泄漏,影響很大,如操作系統、后臺服務等等,出現
內存泄漏會導致響應越來越慢,最終卡死。

void MemoryLeaks()
{// 1.內存申請了忘記釋放int* p1 = (int*)malloc(sizeof(int));int* p2 = new int;// 2.異常安全問題int* p3 = new int[10];Func(); // 這里Func函數拋異常導致 delete[] p3未執行,p3沒被釋放.delete[] p3;
}

?內存泄漏分類

C/C++程序中一般我們關心兩種方面的內存泄漏:
堆內存泄漏(Heap leak)

  • 堆內存指的是程序執行中依據須要分配通過malloc / calloc / realloc / new等從堆中分配的一塊內存,用完后必須通過調用相應的 free或者delete 刪掉。假設程序的設計錯誤導致這部分內存沒有被釋放,那么以后這部分空間將無法再被使用,就會產生Heap Leak。

系統資源泄漏

  • 指程序使用系統分配的資源,比方套接字、文件描述符、管道等沒有使用對應的函數釋放掉,導致系統資源的浪費,嚴重可導致系統效能減少,系統執行不穩定

____________________

?感謝你的閱讀,希望本文能夠對你有所幫助。如果你喜歡我的內容,記得點贊關注收藏我的博客,我會繼續分享更多的內容。?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/715083.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/715083.shtml
英文地址,請注明出處:http://en.pswp.cn/news/715083.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

180基于matlab的頻率切片小波變換程序(FTWT)

基于matlab的頻率切片小波變換程序&#xff08;FTWT&#xff09;。從一種新的角度出發&#xff0c;通過自由選擇頻率切片函數、引進新尺度參數&#xff0c;在頻率域實現小波變換&#xff0c;該變換能夠很好地刻畫信號各成分之間的相對能量關系。此外&#xff0c;頻率切片小波變…

【InternLM 實戰營筆記】OpenCompass大模型評測

隨著人工智能技術的快速發展&#xff0c; 大規模預訓練自然語言模型成為了研究熱點和關注焦點。OpenAI于2018年提出了第一代GPT模型&#xff0c;開辟了自然語言模型生成式預訓練的路線。沿著這條路線&#xff0c;隨后又陸續發布了GPT-2和GPT-3模型。與此同時&#xff0c;谷歌也…

探討蘋果 Vision Pro 的 AI 數字人形象問題

Personas 的設計模糊性&#xff1a; 部分人認為這種模糊設計可能是出于安全考慮&#x1f6e1;?。安全角度&#xff1a;Personas 代表著你的 AI 數字形象&#xff0c;在創建時&#xff0c;它相當于你的 AVP&#xff08;生物識別掃描器的存在增加了冒充的難度&#xff09;。如果…

40、網絡編程/TCP和UDP通信模型練習20240229

一、使用TCP模型創建服務器和客戶端完成簡單通信。 服務器代碼&#xff1a; #include<myhead.h> #define SER_IP "192.168.32.130" #define SER_PORT 8888 int main(int argc, const char *argv[]) {//1.創建監聽的套接字int sfd-1;sfdsocket(AF_INET,SOCK_S…

解決 MySQL 未運行但鎖文件存在的問題

查看mysql狀態時&#xff0c;顯示錯誤信息"ERROR! MySQL is not running, but lock file (/var/lock/subsys/mysql) exists"。 解決步驟 1、檢查 MySQL 進程是否正在運行 在繼續之前&#xff0c;我們首先需要確定 MySQL 進程是否正在運行。我們可以使用以下命令檢查…

MBD開發專欄介紹

文章目錄 MBD概念MBD工具箱介紹MBD專欄介紹MBD概念 MBD : Model-Based Design,基于模型的設計方法是一種系統開發方法論,即對系統進行建模、分析、驗證,然后基于模型自動生成代碼、測試用例和文檔的設計開發過程MBD采用的是基于自然語言和圖形語言的雙重建模方式,讓模型與用…

港中文聯合MIT提出超長上下文LongLoRA大模型微調算法

論文名稱&#xff1a; LongLoRA: Efficient Fine-tuning of Long-Context Large Language Models 文章鏈接&#xff1a;https://arxiv.org/abs/2309.12307 代碼倉庫&#xff1a; https://github.com/dvlab-research/LongLoRA 現階段&#xff0c;上下文窗口長度基本上成為了評估…

算法修煉-動態規劃之路徑問題(1)

62. 不同路徑 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;選定一個網格為終點&#xff0c;走到這個網格的所有走法就是這個網格的上面一個網格的所有走法加上這個網格左邊一個網格的所有走法&#xff0c;然后做好初始化工作就行。 class Solution { public:int…

MATLAB環境下基于偏置場校正的改進模糊c-均值聚類圖像分割算法

基于聚類的分割方法是以統計學為基礎提出的一種分割方法。其實質是通過計算像素與每一類聚類中心的歐氏距離來判定像素與每一類聚類中心的相似性&#xff0c;距離近就說明像素與聚類中心相似性大&#xff0c;反之相似性小。基于一定標準下的相似性自動劃分成若干個子集(類)&…

markdown筆記(自用)

一.標題語法#空格&#xff0c;幾個#就是幾級標題 四級標題<H> 二.段落語法 用空白行分開 你好 三.換行 在一行的末尾添加兩個或多個空格&#xff0c;然后 v vvvvv 按回車鍵,即可創建一個換行()。 換行與段落的區別在于換行后兩行是挨著的&#xff0c;而段落之間有一…

項目預備知識

導入兩個頭文件 #include <graphics.h> // 引入 EasyX 的圖形庫頭文件 #include <conio.h> // 引入 conio.h 以使用 getch() 窗口創建函數&#xff1a;小黑屏 initgraph(640, 480, SHOWCONSOLE); closegraph(); //關閉一個窗口 設置背景顏色&#xff1a;這…

10.7、華為數通HCIP-DataCom H12-821單選題:121-140

121、關于OSPF特性描述錯誤的是:D A、OSPF采用鏈路狀態算法。 B、每個路由器通過泛洪 LSA 向外發布本地鏈路狀態信息 C、每臺 OSPF 設備都會收集其它路由器發來的LSA 所有的LSA 放在一起便組成了鏈路狀態數據庫LSDB, D、OSPF 區域0中所有路由器的 LSDB 都相同。 E、每臺…

【無標題】TMGM官網平臺切爾西足球俱樂部合作

TMGM作為一家在三大洲均設有辦事處的行業領導者&#xff0c;TMGM 被視為可靠的差價合約交易提供商&#xff0c;其重點是監管合規、技術創新與他聯系?&#x1f6f0;?TMGM818卓越的客戶服務。 切爾西足球俱樂部在亞太地區擁有龐大的球迷群體&#xff0c;并在該地區建立了多種亞…

2024年騰訊云優惠政策_騰訊云TOP10優惠活動

騰訊云服務器多少錢一年&#xff1f;62元一年起&#xff0c;2核2G3M配置&#xff0c;騰訊云2核4G5M輕量應用服務器218元一年、756元3年&#xff0c;4核16G12M服務器32元1個月、312元一年&#xff0c;8核32G22M服務器115元1個月、345元3個月&#xff0c;騰訊云服務器網txyfwq.co…

AOP案例(黑馬學習筆記)

需求 需求&#xff1a;將案例中增、刪、改相關接口的操作日志記錄到數據庫表中 ● 就是當訪問部門管理和員工管理當中的增、刪、改相關功能接口時&#xff0c;需要詳細的操作日志&#xff0c;并保存在數據表中&#xff0c;便于后期數據追蹤。 操作日志信息包含&#xff1a; ●…

IO多路轉接

1.select 初識select 系統提供 select 函數來實現多路復用輸入 / 輸出模型 . select 系統調用是用來讓我們的程序監視多個文件描述符的狀態變化的 ; 程序會停在 select 這里等待&#xff0c;直到被監視的文件描述符有一個或多個發生了狀態改變 ; select函數模型 select的函…

服務器硬件得基礎知識介紹

服務器硬件是計算機硬件的一種&#xff0c;專門用于構建服務器系統。服務器硬件通常具有高性能、高可靠性和可擴展性等特點&#xff0c;以滿足企業級應用的需求。本文將從以下幾個方面介紹服務器硬件的基礎知識&#xff1a;服務器概述、CPU、內存、存儲、網絡、電源和散熱、服務…

【機器學習】CIFAR-10數據集簡介、下載方法(自動)

【機器學習】CIFAR-10數據集簡介、下載方法(自動) &#x1f308; 個人主頁&#xff1a;高斯小哥 &#x1f525; 高質量專欄&#xff1a;Matplotlib之旅&#xff1a;零基礎精通數據可視化、Python基礎【高質量合集】、PyTorch零基礎入門教程&#x1f448; 希望得到您的訂閱和支…

0904多元復合函數求導-多元函數微分法及其應用

文章目錄 1 復習一元函數復合函數求導2 一元函數與多元函數復合的情形3 多元函數與多元函數復合的情形4 其他情形5 抽象復合函數求導6 全微分不變性結語 1 復習一元函數復合函數求導 y f ( u ) , u ? ( x ) ? f [ ? ( x ) ] d y d x d y d u ? d u d x f ′ ( u ) ? ?…

Python正則表達式:從基礎到高級應用的全面總結與實戰【第103篇—JSON模塊】

Python正則表達式&#xff1a;從基礎到高級應用的全面總結與實戰 正則表達式是一種強大的文本匹配和處理工具&#xff0c;廣泛應用于文本處理、數據抽取、表單驗證等領域。本文將從正則表達式的基礎知識出發&#xff0c;逐步深入&#xff0c;最終結合代碼實戰&#xff0c;帶你…