程序內存佈局場景下,堆與棧表示兩種內存管理方式:html
1.內部分配時,堆和棧表示兩種不一樣的內存管理方式。c++
2.在討論數據結構時候,堆和棧表示兩種不一樣的數據結構。程序員
棧由操做系統自動分配釋放 ,用於存放函數的參數值、局部變量等,其操做方式相似於數據結構中的棧.數組
int main() 數據結構
{ 函數
int b; //棧佈局
char s[] = "abc"; //棧學習
char *p2; //棧spa
}操作系統
其中函數中定義的局部變量按照前後定義的順序依次壓入棧中,也就是說相鄰變量的地址之間不會存在其它變量。
棧的內存地址生長方向與堆相反,由高到底,因此後定義的變量地址低於先定義的變量,好比上面代碼中變量 s 的地址小於變量 b 的地址,p2 地址小於 s 的地址。
棧中存儲的數據的生命週期隨着函數的執行完成而結束。
堆由開發人員分配和釋放, 若開發人員不釋放,程序結束時由 OS 回收,分配方式相似於鏈表。堆中存儲的數據若未釋放,則其生命週期等同於程序的生命週期。
堆的內存地址生長方向與棧相反,由低到高,可是順序不必定固定由於開發者可能釋放掉了以前分配的內存,致使後分配的內存直接佔用了已經被釋放的舊內存。
關於堆上內存空間的分配過程,首先應該知道操做系統有一個記錄空閒內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆節點,而後將該節點從空閒節點鏈表中刪除,並將該節點的空間分配給程序。
另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確地釋放本內存空間。因爲找到的堆節點的大小不必定正好等於申請的大小,系統會自動地將多餘的那部分從新放入空閒鏈表。
1.棧由系統管理,因此不用擔憂管理的問題。堆的管理由程序員負責,容易產生內存泄漏等隱患。
2.每一個進程擁有的棧的大小要遠遠小於堆的大小。理論上,程序員可申請的堆大小爲虛擬內存的大小,進程棧的大小 64bits 的 Windows 默認 1MB,64bits 的 Linux 默認 10MB;
3.堆的生長方向向上,內存地址由低到高;棧的生長方向向下,內存地址由高到低。
4.堆只能動態分配。棧能夠靜態分配和動態,靜態分配是由操做系統完成的,好比局部變量的分配。動態分配由alloca函數進行分配,可是棧的動態分配和堆是不一樣的,它的動態分配是由操做系統進行釋放。
5.分配效率不一樣。棧由操做系統自動分配,會在硬件層級對棧提供支持,效率明顯更高。堆則是由C/C++提供的庫函數或運算符來完成申請與管理,實現機制較爲複雜,頻繁的內存申請容易產生內存碎片。顯然,堆的效率比棧要低得多。
6.存放內容不一樣。棧存放的內容,函數返回地址、相關參數、局部變量和寄存器內容等。堆,通常狀況堆頂使用一個字節的空間來存放堆的大小,而堆中具體存放內容是由程序員來填充的。
7.棧不是很靈活,因此不少操做仍然要仰仗堆,好比說分配大量的內存空間。
棧是一種運算受限的線性表.其限制是指只僅容許在表的一端進行插入和刪除操做,這種受限的運算使棧擁有「先進後出」的特性.
棧分順序棧和鏈式棧兩種。棧是一種線性結構,因此可使用數組或鏈表(單向鏈表、雙向鏈表或循環鏈表)做爲底層數據結構。
使用數組實現的棧叫作順序棧,使用鏈表實現的棧叫作鏈式棧,兩者的區別是順序棧中的元素地址連續,鏈式棧中的元素地址不連續。
堆是一種經常使用的樹形結構,是一種特殊的徹底二叉樹,當且僅當知足全部節點的值老是不大於或不小於其父節點的值的徹底二叉樹被稱之爲堆。
堆的這一特性稱之爲堆序性。堆的左右孩子沒有大小的順序。
引用:
https://blog.csdn.net/K346K346/article/details/80849966