注:首先堆和棧可以分為兩種,一種是資料結構,另一種是和記憶體的分配有關,這兩種雖然都有棧和堆,但是兩者關係並不大,
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操作符。
程式在編譯對變數和函式分配記憶體都在棧上進行,且記憶體執行過程中函式呼叫時引數的傳遞在棧上進行。
最後,如果你也想成為程式設計師,想要快速掌握程式設計,這裡為你分享乙個學習企鵝圈子!
程式設計學習書籍:
svn容易混淆點
更新 把他人上傳的 更新到本地環境,你在這個環境下把自己的 合併到這個版本中。提交 將合併好的版本提交到svn,他人再根據你提交的版本開發,保證 不會衝突。值得注意的是,使用svn的目的是多人共享乙個最新的目錄,你在提交的時候最好先更新,更新到最新版本的核對之後再提交。因為如果你不更新直接提交,這段...
容易混淆的const
關鍵字const並不能把變數變為常量!在乙個符號前加上const限定符只是表示這個符號不能被賦值。也就是他的值對於這個符號來說是唯讀的,但它並不防止通過程式的內部的方法來修改這個值。const最有用之處就是他來限定函式的形參,這樣該函式將不會修改實參指標所指的資料,但其他的函式卻可能會修改它。1 可...
this容易混淆的示例
注 this 永遠不會混亂,混亂的是我們而已。this永遠指向當前函式的主人。this混亂 1 新增了定時器 延時器 2 事件繫結 注 函式如果發生了賦值,this就混亂了。示例1和示例2是在事件繫結時出現this混亂的現象 示例1目的 點選頁面上的按鈕時也 能彈出 10 1 2349 50按鈕 5...