基本概念
棧區(qū)(Stack):由編譯器自動分配釋放 侠碧,存放函數(shù)的參數(shù)值凌盯,局部變量等贫导,內(nèi)存的分配是連續(xù)的蔚舀,類似于數(shù)據(jù)結(jié)構(gòu)中的棧。即吃粒,所分配的內(nèi)存是在一塊連續(xù)的內(nèi)存區(qū)域內(nèi).當我們聲明變量時潦俺,那么編譯器會自動接著當前棧區(qū)的結(jié)尾來分配內(nèi)存
堆區(qū)(Heap):一般由程序員分配釋放, 若程序員不釋放徐勃,程序結(jié)束時可能由操作系統(tǒng)回收.類似于鏈表事示,在內(nèi)存中的分布不是連續(xù)的,它們是不同區(qū)域的內(nèi)存塊通過指針鏈接起來的.一旦某一節(jié)點從鏈中斷開僻肖,我們要人為的把所斷開的節(jié)點從內(nèi)存中釋放
全局/靜態(tài)區(qū)(Static):全局變量和靜態(tài)變量的存儲是放在一塊的很魂,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域檐涝。 程序結(jié)束后由系統(tǒng)釋放
文字常量區(qū):常量字符串就是放在這里的。 程序結(jié)束后由系統(tǒng)釋放
程序代碼區(qū):存放函數(shù)體的二進制代碼------------------------------------
靜態(tài)分配:程序編譯鏈接時分配的大小和使用壽命就已經(jīng)確定
動態(tài)分配:在程序執(zhí)行的過程中動態(tài)地分配或者回收存儲空間的分配內(nèi)存的方法法挨。動態(tài)內(nèi)存分配不像數(shù)組等靜態(tài)內(nèi)存分配方法那樣需要預(yù)先分配存儲空間谁榜,而是由系統(tǒng)根據(jù)程序的需要即時分配,且分配的大小就是程序要求的大小凡纳。
內(nèi)存泄露:通常是程序自身編碼缺陷造成窃植。用動態(tài)存儲分配函數(shù)動態(tài)開辟的空間,在使用完畢后未釋放荐糜,結(jié)果導(dǎo)致一直占據(jù)該內(nèi)存單元巷怜。直到程序結(jié)束。
內(nèi)存碎片:是一個系統(tǒng)問題暴氏。描述系統(tǒng)中不可以用的空閑內(nèi)存延塑。由于空閑內(nèi)存以小且不連續(xù)方式出現(xiàn)在不同的位置,導(dǎo)致空閑內(nèi)存無法使用答渔,這個與內(nèi)存管理算法息息相關(guān)关带。
內(nèi)部碎片:已經(jīng)被分配出去(能明確指出屬于哪個進程)卻不能被利用的內(nèi)存空間;
內(nèi)部碎片產(chǎn)生原因:因為所有的內(nèi)存分配必須起始于可被 4沼撕、8 或 16 整除(視處理器體系結(jié)構(gòu)而定)的地址或者因為MMU的分頁機制的限制宋雏,決定內(nèi)存分配算法僅能把預(yù)定大小的內(nèi)存塊分配給客戶。假設(shè)當某個客戶請求一個 43 字節(jié)的內(nèi)存塊時务豺,因為沒有適合大小的內(nèi)存磨总,所以它可能會獲得 44字節(jié)、48字節(jié)等稍大一點的字節(jié)笼沥,因此由所需大小四舍五入而產(chǎn)生的多余空間就叫內(nèi)部碎片蚪燕。
外部碎片:指的是還沒有被分配出去(不屬于任何進程)娶牌,但由于太小了無法分配給申請內(nèi)存空間的新進程的內(nèi)存空閑區(qū)域。
外部碎片產(chǎn)生原因:頻繁的分配與回收物理頁面會導(dǎo)致大量的邻薯、連續(xù)且小的頁面塊夾雜在已分配的頁面中間裙戏,就會產(chǎn)生外部碎片。如果一個進程申請了一個8個單位的內(nèi)存空間厕诡,隨后便釋放了累榜。后續(xù)進程申請的內(nèi)存空間都大于8(比如是16,32等)灵嫌。那么這8個單位的空間永遠得不到使用壹罚,變成外部碎片。
理解到底放哪里
int a = 0; //全局初始化區(qū)
char *p1; //全局未初始化區(qū)
main()
{
int b; //棧
char s[] = "abc"; //棧
char *p2; //棧
char *p3 = "123456"; //123456\0在常量區(qū)寿羞,p3在棧上猖凛。
static int c =0; //全局(靜態(tài))初始化區(qū)
p1 = (char *)malloc(10); //堆
p2 = (char *)malloc(20); //堆
}
堆內(nèi)存與棧內(nèi)存的區(qū)別
申請和回收方式不同:棧上的空間是自動分配自動回收的绪穆,所以棧上的數(shù)據(jù)的生存周期只是在函數(shù)的運行過程中辨泳,運行后就釋放掉,不可以再訪問玖院。而堆上的數(shù)據(jù)只要程序員不釋放空間菠红,就一直可以訪問到,不過缺點是一旦忘記釋放會造成內(nèi)存泄露难菌。
碎片問題:對于棧试溯,不會產(chǎn)生不連續(xù)的內(nèi)存塊;但是對于堆來說郊酒,不斷的new遇绞、delete勢必會產(chǎn)生上面所述的內(nèi)部碎片和外部碎片。
申請大小的限制:棧是向低地址擴展的數(shù)據(jù)結(jié)構(gòu)燎窘,是一塊連續(xù)的內(nèi)存的區(qū)域摹闽。棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的,如果申請的空間超過棧的剩余空間荠耽,就會產(chǎn)生棧溢出钩骇;對于堆,是向高地址擴展的數(shù)據(jù)結(jié)構(gòu)铝量,是不連續(xù)的內(nèi)存區(qū)域倘屹。堆的大小受限于計算機系統(tǒng)中有效的虛擬內(nèi)存。由此可見慢叨,堆獲得的空間比較靈活纽匙,也比較大。
申請效率的比較:棧由系統(tǒng)自動分配拍谐,速度較快烛缔。但程序員是無法控制的馏段;堆:是由new分配的內(nèi)存,一般速度比較慢践瓷,而且容易產(chǎn)生內(nèi)存碎片,不過用起來最方便院喜。
當然還有存儲內(nèi)容的不一樣
【文章來源簡書:Martin_wjl 】