關(guān)于內(nèi)存的理解

首先了解一下什么是內(nèi)存:
內(nèi)存是計(jì)算機(jī)中重要的部件之一,它是與CPU進(jìn)行溝通的橋梁。計(jì)算機(jī)中所有程序的運(yùn)行都是在內(nèi)存中進(jìn)行的,因此內(nèi)存的性能對(duì)計(jì)算機(jī)的影響非常大。內(nèi)存(Memory)也被稱為內(nèi)存儲(chǔ)器,其作用是用于暫時(shí)存放CPU中的運(yùn)算數(shù)據(jù),以及與硬盤等外部存儲(chǔ)器交換的數(shù)據(jù)。只要計(jì)算機(jī)在運(yùn)行中,CPU就會(huì)把需要運(yùn)算的數(shù)據(jù)調(diào)到內(nèi)存中進(jìn)行運(yùn)算,當(dāng)運(yùn)算完成后CPU再將結(jié)果傳送出來,內(nèi)存的運(yùn)行也決定了計(jì)算機(jī)的穩(wěn)定運(yùn)行。
內(nèi)存從高地址到低地址的順序依次為:棧區(qū)、堆區(qū)、BSS段、數(shù)據(jù)區(qū)、代碼段


(棧區(qū)是從高地址到低地址存儲(chǔ),堆區(qū)是從低地址到高地址存儲(chǔ))

棧區(qū):是在編譯器需要的時(shí)候分配,不需要的時(shí)候自動(dòng)釋放和清除變量的存儲(chǔ)區(qū)。棧區(qū)存儲(chǔ)的是局部變量、函數(shù)的參數(shù)等,在一個(gè)進(jìn)程中,位于地址空間頂部的是用戶棧,編譯器用它來實(shí)現(xiàn)函數(shù)調(diào)用。

堆區(qū):動(dòng)態(tài)分配的內(nèi)存。就是在實(shí)例化一個(gè)對(duì)象的時(shí)候,系統(tǒng)分配給對(duì)象的內(nèi)存塊,這塊內(nèi)存需要程序員進(jìn)行手動(dòng)釋放,編譯器并不會(huì)自動(dòng)釋放這塊內(nèi)存,(在實(shí)例化一個(gè)對(duì)象的時(shí)候同時(shí)創(chuàng)建一個(gè)與類的對(duì)象名相同的指針,這個(gè)指針存放在棧區(qū),在代碼結(jié)束時(shí)編譯器會(huì)釋放棧區(qū)的內(nèi)存,這樣對(duì)象的指針就不存在了,如果程序員不去手動(dòng)釋放分配給對(duì)象的內(nèi)存塊,就會(huì)造成內(nèi)存泄露(Memory leak))

BSS段:存放的是未被初始化的全局變量和靜態(tài)變量。

數(shù)據(jù)區(qū):存放的是已經(jīng)被初始化的全局變量和靜態(tài)變量,還有一些字符常量、常量等。

代碼段:存放的是被編譯之后的二進(jìn)制的代碼的內(nèi)容。

關(guān)于 堆 棧 的區(qū)別

區(qū)分堆和棧,先舉個(gè)例子:

class person{
public:
 int height;
 int weight;
 int volume();
}
Person *p = new Person;

上面是實(shí)例化一個(gè)對(duì)象的例子,首先,我們給對(duì)象分配了一塊堆內(nèi)存,在棧內(nèi)存中存放了一個(gè)指向?qū)ο蟮亩褍?nèi)存的指針p。堆內(nèi)存申請(qǐng)之后需要程序員的手動(dòng)釋放(delete p)
堆、棧區(qū)別:

釋放:對(duì)于棧區(qū),是由系統(tǒng)自行管理(申請(qǐng)和釋放)。對(duì)于堆區(qū),由程序員管理進(jìn)行控制申請(qǐng)和釋放。
(容易產(chǎn)生內(nèi)存泄露)
存儲(chǔ)方向:對(duì)于棧區(qū),存儲(chǔ)的方向是向下的,從高地址到低地址存儲(chǔ)。對(duì)于堆區(qū),存儲(chǔ)方向是向上的,
從低地址到高低之存儲(chǔ)。
分配:對(duì)于棧區(qū),有兩種的分配方式:靜態(tài)分配和動(dòng)態(tài)分配。靜態(tài)分配是由系統(tǒng)完成(局部變量的內(nèi)存分配),
動(dòng)態(tài)分配由malloc進(jìn)行分配,與堆區(qū)不同,棧區(qū)的動(dòng)態(tài)分配是系統(tǒng)釋放。對(duì)于堆區(qū):都是動(dòng)態(tài)分配的。
效率:棧是機(jī)器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu),計(jì)算機(jī)會(huì)在底層對(duì)棧提供支持:分配專門的寄存器存放棧的地址,
壓棧出棧都有專門的指令執(zhí)行,這就決定了棧的效率比較高。堆則是 C/C++ 函數(shù)庫(kù)提供的,它的機(jī)制是很復(fù)雜的,
例如為了分配一塊內(nèi)存,庫(kù)函數(shù)會(huì)按照一定的算法(具體的算法可以參考數(shù)據(jù)結(jié)構(gòu)/操作系統(tǒng))
在堆內(nèi)存中搜索可用的足夠大小的空間,如果沒有足夠大小的空間(可能是由于內(nèi)存碎片太多),就有可能調(diào)用
系統(tǒng)功能去增加程序數(shù)據(jù)段的內(nèi)存空間,這樣就有機(jī)會(huì)分到足夠大小的內(nèi)存,然后進(jìn)行返回。
顯然,堆的效率比棧要低得多。
  從這里我們可以看到,堆和棧相比,由于大量 new/delete 的使用,容易造成大量的內(nèi)存碎片;
由于沒有專門的系統(tǒng)支持,效率很低;由于可能引發(fā)用戶態(tài)和核心態(tài)的切換,內(nèi)存的申請(qǐng),代價(jià)變得更加昂貴。
所以棧在程序中是應(yīng)用最廣泛的,就算是函數(shù)的調(diào)用也利用棧去完成,函數(shù)調(diào)用過程中的參數(shù),返回地址,
EBP 和局部變量都采用棧的方式存放。所以,我們推薦大家盡量用棧,而不是用堆。
  雖然棧有如此眾多的好處,但是由于和堆相比不是那么靈活,有時(shí)候分配大量的內(nèi)存空間,還是用堆好一些。
  無論是堆還是棧,都要防止越界現(xiàn)象的發(fā)生(除非你是故意使其越界),因?yàn)樵浇绲慕Y(jié)果要么是程序崩潰,
要么是摧毀程序的堆、棧結(jié)構(gòu),產(chǎn)生以想不到的結(jié)果,就算是在你的程序運(yùn)行過程中,沒有發(fā)生上面的問題,
你還是要小心.

(new 可以認(rèn)為是 malloc 加構(gòu)造函數(shù)的執(zhí)行,new 出來的指針是直接帶類型信息的,而 malloc 返回的都是 void 指針。在執(zhí)行運(yùn)算符 delete 時(shí)相應(yīng)地會(huì)調(diào)用對(duì)象的析構(gòu)函數(shù),而調(diào)用 free 函數(shù)時(shí)則不會(huì)——這是很有用的:當(dāng)你類里面包含了其他類的指針變量并且你在你類的析構(gòu)函數(shù)里面釋放了該指針變量,通過執(zhí)行 delete 運(yùn)算符能隱式調(diào)用對(duì)象的析構(gòu)函數(shù)來釋放指針變量所指向的空間。)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • JVM內(nèi)存模型Java虛擬機(jī)(Java Virtual Machine=JVM)的內(nèi)存空間分為五個(gè)部分,分別是: ...
    光劍書架上的書閱讀 2,775評(píng)論 2 26
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,810評(píng)論 11 349
  • __block和__weak修飾符的區(qū)別其實(shí)是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,596評(píng)論 0 6
  • C語言中內(nèi)存分配 在任何程序設(shè)計(jì)環(huán)境及語言中,內(nèi)存管理都十分重要。在目前的計(jì)算機(jī)系統(tǒng)或嵌入式系統(tǒng)中,內(nèi)存資源仍然是...
    一生信仰閱讀 1,312評(píng)論 0 2
  • 朋友這個(gè)月結(jié)婚,人生第一次,我要當(dāng)伴娘了??偸锹犎苏f當(dāng)伴娘超過三次就嫁不出去了,我想了很久這有什么科學(xué)依據(jù),估摸著...
    lilfreak_閱讀 235評(píng)論 0 2

友情鏈接更多精彩內(nèi)容