注:首先堆和棧可以分為兩種,一種是數據結構,另一種是和內存的分配有關,這兩種雖然都有棧和堆,但是兩者關系並不大,
1、棧、堆是數據結構里面的叫法,注意:有時候有人喜歡這樣說 “堆棧” 其實說的就是棧而不是堆。
2、堆區、棧區則是內存模型的叫法。

內存中的棧區和堆區
堆區:就是通過new、malloc、realloc分配的內存塊,編譯器不會負責它們的釋放工作,需要用程序區釋放。分配方式類似於數據結構中的鏈表。“內存泄漏”通常說的就是堆區。
棧區:存放函數內的局部變量,形參和函數返回值。棧區之中的數據的作用范圍過了之后,系統就會回收自動管理棧區的內存(分配內存 , 回收內存),不需要開發人員來手動管理。棧區就像是一家客棧,里面有很多房間,客人來了之后自動分配房間,房間里的客人可以變動,是一種動態的數據變動。
堆和棧有什么區別?
堆(Heap)和棧(Stack)是有區別的,很多程序員混淆堆棧的概念,或者認為它們就是一個概念。簡單來說,它們之間的主要區別可以表現在如下五個方面。
1.分配和管理方式不同
堆是動態分配的,其空間的分配和釋放都由程序員控制。也就是說,堆的大小並不固定,可動態擴張或縮減,其分配由malloc()等這類實時內存分配函數來實現。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)。
而棧由編譯器自動管理,其分配方式有兩種:靜態分配和動態分配。靜態分配由編譯器完成,比如局部變量的分配。動態分配由alloca()函數進行分配,但是棧的動態分配和堆是不同的,它的動態分配是由編譯器進行釋放,無需手工控制。
2.申請的大小限制不同
棧是向低地址擴展的數據結構,是一塊連續的內存區域,棧頂的地址和棧的最大容量是系統預先規定好的,能從棧獲得的空間較小。
堆是向高地址擴展的數據結構,是不連續的內存區域,這是由於系統是由鏈表在存儲空閑內存地址,自然堆就是不連續的內存區域,且鏈表的遍歷也是從低地址向高地址遍歷的,堆的大小受限於計算機系統的有效虛擬內存空間,
由此空間,堆獲得的空間比較靈活,也比較大。在 32 位平台下,VC6 下默認為 1M,堆最大可以到 4G;

3.申請效率不同
棧由系統自動分配,速度快,但是程序員無法控制。
堆是有程序員自己分配,速度較慢,容易產生碎片,不過用起來方便。
4.產生碎片不同
對堆來說,頻繁執行malloc或free勢必會造成內存空間的不連續,形成大量的碎片,使程序效率降低;而對棧而言,則不存在碎片問題。
5.內存地址增長的方向不同
堆是向着內存地址增加的方向增長的,從內存的低地址向高地址方向增長;
棧的增長方向與之相反,是向着內存地址減小的方向增長,由內存的高地址向低地址方向增長。
假設一個程序的函數調用順序為:主函數main調用函數func1,函數func1調用函數func2。當這個程序被操作系統調入內存運行時,其對應的進程在內存中的映射結果如下圖所示

例子中的內存映射
進程的棧是由多個棧幀構成的,其中每個棧幀都對應一個函數調用。當調用函數時,新的棧幀被壓入棧;當函數返回時,相應的棧幀從棧中彈出。由於需要將函數返回地址這樣的重要數據保存在程序員可見的堆棧中,因此也給系統安全帶來了極大的隱患。
當程序寫入超過緩沖區的邊界時,就會產生所謂的“緩沖區溢出”。發生緩沖區溢出時,就會覆蓋下一個相鄰的內存塊,導致程序發生一些不可預料的結果:也許程序可以繼續,也許程序的執行出現奇怪現象,也許程序完全失敗或者崩潰等。

總結:
(1)heap是堆,stack是棧;
(2)stack的空間由操作系統自動分配/釋放,heap上的空間手動分配/釋放;
(3)stack空間有限,heap是很大的自由內存區;
(4)C中的malloc函數分配的內存空間即在堆上,C++中對應的是new操作符。
程序在編譯對變量和函數分配內存都在棧上進行,且內存運行過程中函數調用時參數的傳遞在棧上進行。

最后,如果你也想成為程序員,想要快速掌握編程,這里為你分享一個學習企鵝圈子!
里面有資深專業軟件開發工程師,在線解答你的所有疑惑~編程語言入門“so easy”
編程學習書籍:

編程學習視頻:
