欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語(yǔ)言與C++中內(nèi)存管理詳解

 更新時(shí)間:2022年04月15日 15:37:01   作者:m0_52012656  
本章主要介紹C語(yǔ)言與C++的內(nèi)存管理,以C++的內(nèi)存分布作為引入,介紹C++不同于C語(yǔ)言的內(nèi)存管理方式(new?delete對(duì)比?malloc?free),感興趣的朋友來(lái)看看吧

內(nèi)存分布

主要段及其分布

? 每個(gè)程序運(yùn)行起來(lái)以后,它將擁有自己獨(dú)立的虛擬地址空間。這個(gè)虛擬地址空間的大小與操作系統(tǒng)的位數(shù)有關(guān)系。32位硬件平臺(tái)的虛擬地址空間的地址可以從0~2^32-1,即0x00000000~0xFFFFFFFF,總共4GB大小。64位硬件平臺(tái)的虛擬地址空間則會(huì)很大。C/C++程序在虛擬內(nèi)存中的排布大概如下所示(僅僅列出了相關(guān)的主要段):

如上圖所示:

1、棧區(qū)(stack)— 由編譯器自動(dòng)分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。

2、堆區(qū)(heap) — 一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時(shí)可能由OS回收 。注意它與數(shù)據(jù)結(jié)構(gòu)中的堆是兩回事,分配方式倒是類似于鏈表,注意不釋放的話會(huì)造成內(nèi)存泄漏。

3、數(shù)據(jù)段(靜態(tài)區(qū))(static)—,全局變量和靜態(tài)變量的存儲(chǔ)是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。 - 程序結(jié)束后由系統(tǒng)釋放。

4、內(nèi)存映射段是高效的I/O映射方式,用于裝載一個(gè)共享的動(dòng)態(tài)內(nèi)存庫(kù)。用戶可使用系統(tǒng)接口創(chuàng)建共享共享內(nèi)存,做進(jìn)程間通信。

5、代碼段—存放函數(shù)體的二進(jìn)制代碼,直接的操作數(shù)也是存儲(chǔ)在這個(gè)位置的。如int a=4;。

動(dòng)態(tài)內(nèi)存管理方式-堆區(qū)

C語(yǔ)言動(dòng)態(tài)內(nèi)存管理

C語(yǔ)言中使用malloc/calloc/realloc/free四個(gè)函數(shù)來(lái)進(jìn)行動(dòng)態(tài)內(nèi)存管理

1、malloc:用來(lái)動(dòng)態(tài)申請(qǐng)一塊內(nèi)存,但不初始化。

2、calloc: 動(dòng)態(tài)申請(qǐng)一塊內(nèi)存,但會(huì)將申請(qǐng)出的內(nèi)存初始化為0。

3、realloc: 當(dāng)申請(qǐng)出的內(nèi)存不夠用時(shí),會(huì)使用realloc來(lái)動(dòng)態(tài)擴(kuò)容(會(huì)有一定程度的消耗)。

4、free: 用來(lái)釋放動(dòng)態(tài)申請(qǐng)的的內(nèi)存(當(dāng)內(nèi)存不用時(shí)一定要使用free來(lái)釋放它,否則會(huì)造成內(nèi)存泄漏)

C++動(dòng)態(tài)內(nèi)存管理

? 因?yàn)镃++是兼容C的也可以使用上述的幾個(gè)函數(shù)來(lái)進(jìn)行內(nèi)存管理,但是C++中引入了new/delete兩個(gè)操作符來(lái)進(jìn)行內(nèi)存的申請(qǐng)和釋放。

new和delete的用法

1、操作內(nèi)置類型

//申請(qǐng)單個(gè)對(duì)象
int *p1=new int;//動(dòng)態(tài)申請(qǐng)一塊int類型的空間。
int *p2=new int(3);//動(dòng)態(tài)申請(qǐng)一塊int類型的空間,并將其初始化。
?
delete p1;
delete p2;
?
//動(dòng)態(tài)申請(qǐng)一塊連續(xù)空間
int *p3=new int[10];//[]中是對(duì)象個(gè)數(shù)
?
//釋放
delete [] p3;

注意:申請(qǐng)和釋放單個(gè)元素的空間,使用new和delete操作符,申請(qǐng)和釋放連續(xù)的空間,使用new[]和delete[]。

2、操作自定義類型

class Test
{
public:
    Test()
        : _data(0)
    {
        cout<<"Test():"<<this<<endl;
    }
    ~Test()
    {
        cout<<"~Test():"<<this<<endl;
    }
private:
    int _data;
};
int main()
{
    //申請(qǐng)單個(gè)自定義類型的空間
    Test* p1=new Test;
    delete p1;
    
    //申請(qǐng)多個(gè)自定義類型的連續(xù)空間
    Test* p2= new Test[10];
    delete [] p2;
    
    return 0;
}

注意:在申請(qǐng)自定義類型的空間時(shí),new會(huì)調(diào)用構(gòu)造函數(shù),delete會(huì)調(diào)用析構(gòu)函數(shù),而malloc與free不會(huì)。

operator new與operator delete函數(shù)

new和delete是用戶進(jìn)行動(dòng)態(tài)內(nèi)存申請(qǐng)和釋放的操作符,operator new和operator delete是系統(tǒng)提供的全局函數(shù),new在底層調(diào)用operator new全局函數(shù)來(lái)申請(qǐng)空間,delete在底層通過(guò)operator delete全局函數(shù)來(lái)釋放空間。

operator new:該函數(shù)實(shí)際通過(guò)malloc來(lái)申請(qǐng)空間,當(dāng)malloc申請(qǐng)空間成功時(shí)直接返回;申請(qǐng)空間失敗,嘗試執(zhí)行空間不足應(yīng)對(duì)措施,如果改應(yīng)對(duì)措施用戶1設(shè)置了,則繼續(xù)申請(qǐng),否則拋異常。

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

operator delete:該函數(shù)實(shí)際通過(guò)free來(lái)釋放空間的。

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;
}

new和delete的實(shí)現(xiàn)原理

1、內(nèi)置類型

? 如果申請(qǐng)的是內(nèi)置類型的空間,new和malloc,delete和free基本類似,不同的地方是:new/delete申請(qǐng)和釋放的是單個(gè)元素的空間,new[]和delete[]申請(qǐng)的是連續(xù)空間,而且new在申請(qǐng)空間失敗時(shí)會(huì)拋異常,malloc會(huì)返回NULL

2、自定義類型

new的原理

  • 1、調(diào)用operator new 函數(shù)申請(qǐng)空間
  • 2、在申請(qǐng)的空間上執(zhí)行構(gòu)造函數(shù),完成對(duì)象的構(gòu)造

delete的原理

  • 1、調(diào)用operatordelete 函數(shù)釋放空間
  • 2、在空間上執(zhí)行析構(gòu)函數(shù),完成對(duì)象中資源的清理工作

new T[N]的原理

  • 1、調(diào)用operator new[]函數(shù),在operator new[]中實(shí)際調(diào)用operator new函數(shù)完成N個(gè)對(duì)象空間的申請(qǐng)
  • 2、在申請(qǐng)的空間上執(zhí)行N次構(gòu)造函數(shù)

delete[]的原理

  • 1、在釋放的對(duì)象空間上執(zhí)行N次析構(gòu)函數(shù),完成N個(gè)對(duì)象中資源的清理
  • 2、調(diào)用operator delete[]釋放空間,實(shí)際在operator delete[]中調(diào)用operator delete來(lái)釋放空間

定位new表達(dá)式

定位new表達(dá)式是在已分配的原始內(nèi)存空間中調(diào)用構(gòu)造函數(shù)初始化一個(gè)對(duì)象。

使用格式:

new (place_address) type或者new (place_address) type(initializer-list)

place_address必須是一個(gè)指針,initializer-list是類型的初始化列表

使用場(chǎng)景:

定位new表達(dá)式在實(shí)際中一般是配合內(nèi)存池使用。因?yàn)閮?nèi)存池分配出的內(nèi)存沒(méi)有初始化,所以如果是自定義類型的對(duì)象,需要使用new的定義表達(dá)式進(jìn)行顯示調(diào)構(gòu)造函數(shù)進(jìn)行初始化。

class Test
{
public:
    Test()
        : _data(0)
    {
        cout<<"Test():"<<this<<endl;
    }
    ~Test()
    {
        cout<<"~Test():"<<this<<endl;
    }
private:
    int _data;
};
void Test()
{
    // pt現(xiàn)在指向的只不過(guò)是與Test對(duì)象相同大小的一段空間,還不能算是一個(gè)對(duì)象,因?yàn)闃?gòu)造函數(shù)沒(méi)有執(zhí)行
    Test* pt = (Test*)malloc(sizeof(Test));
    new(pt) Test; // 注意:如果Test類的構(gòu)造函數(shù)有參數(shù)時(shí),此處需要傳參
}

高頻面試題

重點(diǎn)new/delete和malloc/free的區(qū)別

1、 屬性

new/delete是C++關(guān)鍵字,需要編譯器支持。malloc/free是庫(kù)函數(shù),需要頭文件支持。

2、 參數(shù)

使用new操作符申請(qǐng)內(nèi)存分配時(shí)無(wú)須指定內(nèi)存塊的大小,編譯器會(huì)根據(jù)類型信息自行計(jì)算。而malloc則需要顯式地指出所需內(nèi)存的尺寸。

3、 返回類型

new操作符內(nèi)存分配成功時(shí),返回的是對(duì)象類型的指針,類型嚴(yán)格與對(duì)象匹配,無(wú)須進(jìn)行類型轉(zhuǎn)換,故new是符合類型安全性的操作符。而malloc內(nèi)存分配成功則是返回void * ,需要通過(guò)強(qiáng)制類型轉(zhuǎn)換將void*指針轉(zhuǎn)換成我們需要的類型。

4、 分配失敗

new內(nèi)存分配失敗時(shí),會(huì)拋出bac_alloc異常。malloc分配內(nèi)存失敗時(shí)返回NULL。

5、 自定義類型

new會(huì)先調(diào)用operator new函數(shù),申請(qǐng)足夠的內(nèi)存(通常底層使用malloc實(shí)現(xiàn))。然后調(diào)用類型的構(gòu)造函數(shù),初始化成員變量,最后返回自定義類型指針。delete先調(diào)用析構(gòu)函數(shù),然后調(diào)用operator delete函數(shù)釋放內(nèi)存(通常底層使用free實(shí)現(xiàn))。

malloc/free是庫(kù)函數(shù),只能動(dòng)態(tài)的申請(qǐng)和釋放內(nèi)存,無(wú)法強(qiáng)制要求其做自定義類型對(duì)象構(gòu)造和析構(gòu)工作。

6、 重載

C++允許重載new/delete操作符,特別的,布局new的就不需要為對(duì)象分配內(nèi)存,而是指定了一個(gè)地址作為內(nèi)存起始區(qū)域,new在這段內(nèi)存上為對(duì)象調(diào)用構(gòu)造函數(shù)完成初始化工作,并返回此地址。而malloc不允許重載。

7、 內(nèi)存區(qū)域

new操作符從自由存儲(chǔ)區(qū)(free store)上為對(duì)象動(dòng)態(tài)分配內(nèi)存空間,而malloc函數(shù)從堆上動(dòng)態(tài)分配內(nèi)存。自由存儲(chǔ)區(qū)是C++基于new操作符的一個(gè)抽象概念,凡是通過(guò)new操作符進(jìn)行內(nèi)存申請(qǐng),該內(nèi)存即為自由存儲(chǔ)區(qū)。而堆是操作系統(tǒng)中的術(shù)語(yǔ),是操作系統(tǒng)所維護(hù)的一塊特殊內(nèi)存,用于程序的內(nèi)存動(dòng)態(tài)分配,C語(yǔ)言使用malloc從堆上分配內(nèi)存,使用free釋放已分配的對(duì)應(yīng)內(nèi)存。自由存儲(chǔ)區(qū)不等于堆,如上所述,布局new就可以不位于堆中。

內(nèi)存泄漏

1、什么是內(nèi)存泄漏,內(nèi)存泄漏的危害什么是內(nèi)存泄漏:內(nèi)存泄漏指因?yàn)槭韬龌蝈e(cuò)誤造成程序未能釋放已經(jīng)不再使用的內(nèi)存的情況。內(nèi)存泄漏并不是指內(nèi)存在物理上的消失,而是應(yīng)用程序分配某段內(nèi)存后,因?yàn)樵O(shè)計(jì)錯(cuò)誤,失去了對(duì)該段內(nèi)存的控制,因而造成了內(nèi)存的浪費(fèi)。

內(nèi)存泄漏的危害:長(zhǎng)期運(yùn)行的程序出現(xiàn)內(nèi)存泄漏,影響很大,如操作系統(tǒng)、后臺(tái)服務(wù)等等,出現(xiàn)內(nèi)存泄漏會(huì)導(dǎo)致響應(yīng)越來(lái)越慢,最終卡死。

2、內(nèi)存泄漏分類

C/C++程序中一般我們關(guān)心兩種方面的內(nèi)存泄漏:

  • 堆內(nèi)存泄漏

堆內(nèi)存指的是程序執(zhí)行中依據(jù)須要分配通過(guò)malloc / calloc / realloc / new等從堆中分配的一塊內(nèi)存,用完后必須通過(guò)調(diào)用相應(yīng)的 free或者delete 刪掉。假設(shè)程序的設(shè)計(jì)錯(cuò)誤導(dǎo)致這部分內(nèi)存沒(méi)有被釋放,那么以后這部分空間將無(wú)法再被使用,就會(huì)產(chǎn)生Heap Leak

  • 系統(tǒng)資源泄漏

指程序使用系統(tǒng)分配的資源,比方套接字、文件描述符、管道等沒(méi)有使用對(duì)應(yīng)的函數(shù)釋放掉,導(dǎo)致系統(tǒng)資源的浪費(fèi),嚴(yán)重可導(dǎo)致系統(tǒng)效能減少,系統(tǒng)執(zhí)行不穩(wěn)定

3、如何避免內(nèi)存泄漏

工程前期良好的設(shè)計(jì)規(guī)范,養(yǎng)成良好的編碼規(guī)范,申請(qǐng)的內(nèi)存空間記著匹配的去釋放。ps:這個(gè)理想狀態(tài)。但是如果碰上異常時(shí),就算注意釋放了,還是可能會(huì)出問(wèn)題。需要下一條智能指針來(lái)管理才有保證。

采用RAII思想或者智能指針來(lái)管理資源。

有些公司內(nèi)部規(guī)范使用內(nèi)部實(shí)現(xiàn)的私有內(nèi)存管理庫(kù)。這套庫(kù)自帶內(nèi)存泄漏檢測(cè)的功能選項(xiàng)。

出問(wèn)題了使用內(nèi)存泄漏工具檢測(cè)。ps:不過(guò)很多工具都不夠靠譜,或者收費(fèi)昂貴。

總結(jié)一下:

內(nèi)存泄漏非常常見(jiàn),解決方案分為兩種:1、事前預(yù)防型。如智能指針等。2、事后查錯(cuò)型。如泄漏檢測(cè)工具

到此這篇關(guān)于C語(yǔ)言與C++中內(nèi)存管理詳解的文章就介紹到這了,更多相關(guān)C語(yǔ)言 內(nèi)存管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語(yǔ)言實(shí)現(xiàn)圖形化打磚塊游戲

    C語(yǔ)言實(shí)現(xiàn)圖形化打磚塊游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)圖形化打磚塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C++ 在 Unreal 中為游戲增加實(shí)時(shí)音視頻互動(dòng)的教程詳解

    C++ 在 Unreal 中為游戲增加實(shí)時(shí)音視頻互動(dòng)的教程詳解

    這篇文章主要介紹了C++ 在 Unreal 中為游戲增加實(shí)時(shí)音視頻互動(dòng)的教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • C++中讀寫(xiě)txt文件并分離字符的方法

    C++中讀寫(xiě)txt文件并分離字符的方法

    今天小編就為大家分享一篇C++中讀寫(xiě)txt文件并分離字符的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • C++實(shí)現(xiàn)讀取圖片長(zhǎng)度和寬度

    C++實(shí)現(xiàn)讀取圖片長(zhǎng)度和寬度

    這篇文章主要介紹了C++實(shí)現(xiàn)讀取圖片長(zhǎng)度和寬度,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2015-04-04
  • C++利用libcurl獲取下載文件名稱及大小

    C++利用libcurl獲取下載文件名稱及大小

    這篇文章主要為大家詳細(xì)介紹了C++如何利用libcurl獲取下載文件名稱及大小的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-03-03
  • C/C++常用函數(shù)易錯(cuò)點(diǎn)分析

    C/C++常用函數(shù)易錯(cuò)點(diǎn)分析

    這篇文章主要介紹了C/C++常用函數(shù)易錯(cuò)點(diǎn)分析,包含了memset、sizeof、getchar三個(gè)常用函數(shù)的分析,需要的朋友可以參考下
    2014-08-08
  • C語(yǔ)言修煉之路數(shù)據(jù)類型悟正法?解析存儲(chǔ)定風(fēng)魔上篇

    C語(yǔ)言修煉之路數(shù)據(jù)類型悟正法?解析存儲(chǔ)定風(fēng)魔上篇

    使用編程語(yǔ)言進(jìn)行編程時(shí),需要用到各種變量來(lái)存儲(chǔ)各種信息。變量保留的是它所存儲(chǔ)的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個(gè)變量時(shí),就會(huì)在內(nèi)存中保留一些空間。您可能需要存儲(chǔ)各種數(shù)據(jù)類型的信息,操作系統(tǒng)會(huì)根據(jù)變量的數(shù)據(jù)類型,來(lái)分配內(nèi)存和決定在保留內(nèi)存中存儲(chǔ)什么
    2022-02-02
  • socket編程的詳細(xì)講解

    socket編程的詳細(xì)講解

    本文詳細(xì)講解了socket編程,它是網(wǎng)絡(luò)中經(jīng)常使用的一門(mén)技術(shù),該文章通過(guò)大量的代碼來(lái)解釋,大家可以參考參考
    2021-08-08
  • MFC對(duì)話框自定義消息映射的方法

    MFC對(duì)話框自定義消息映射的方法

    這篇文章主要介紹了MFC對(duì)話框自定義消息映射的方法,實(shí)例分析了MFC自定義消息映射的消息定義、響應(yīng)、聲明及實(shí)現(xiàn)消息映射的相關(guān)技巧,需要的朋友可以參考下
    2015-07-07
  • C++實(shí)現(xiàn)俄羅斯方塊源碼

    C++實(shí)現(xiàn)俄羅斯方塊源碼

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)俄羅斯方塊源碼完整版,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06

最新評(píng)論