c++堆栈溢出怎么解决_c语言进阶:堆栈原理揭秘
學習C語言時,初學者常常被教材上一股腦拋出來的諸如“字符串”,“指針”,“鏈表”等概念搞得暈頭轉向,再加上教材重概念,輕運用的敘述方式,這些名稱就越發令人生畏。“堆棧”,“溢出”,“跑飛”也從本應很實用的概念變成了虛幻,令人難以捉摸的名詞。
其實這些C語言的概念就像瑞士軍刀上的一個個小組件,都是為了方便解決特定問題而設計的。接下來博主將嘗試用另一種打開方式,講解“堆棧(stack)”這把c語言的刀到底是為何被設計出來,又是為了方便切啥的。
目錄:
1. 什么是堆棧?
2. 為什么需要堆棧?
3. 堆棧的功能是怎么實現的?
4. Reference:
讓我們先重溫一下百度百科里,每一個字都看得懂,但是不知道在說什么的堆棧定義:
1. 什么是堆棧?
單片機應用中,堆棧是個特殊存儲區,堆棧屬于RAM空間的一部分,堆棧用于函數調用、中斷切換時保存和恢復現場數據。堆棧中的物體具有一個特性:第一個放入堆棧中的物體總是被最后拿出來, 這個特性通常稱為先進后出 (FILO—First-In/Last-Out)。 堆棧中定義了一些操作, 兩個最重要的是PUSH和POP。 PUSH(入棧)操作:堆棧指針(SP)加1,然后在堆棧的頂部加入一 個元素。POP(出棧)操作相反,出棧則先將SP所指示的內部ram單元中內容送入直接地址尋址的單元中(目的位置),然后再將堆棧指針(SP)減1。這兩種操作實現了數據項的插入和刪除。
接下來博主嘗試將百度百科試圖傳遞的信息翻譯為人話:
2. 為什么需要堆棧?
首先,為什么需要堆棧?真的是搞計算機的那幫宅男吃飽了撐的嗎?
【編者注:必須不是!魯迅曾經說過:“不想偷懶的程序員不是好程序員”,就算是吃撐了,程序員也只會是選擇來知乎摸魚】 其實每個看起來很玄乎的計算機概念,都是程序員為了以后能更方便的解決問題(偷懶)而提出的。
言歸正傳,堆棧其實是為了減少程序內存(RAM)占用的的問題而發明的。出于成本的考慮,單片機的內存容量一直都是非常有限的。而在單片機上電后,所有的變量又都需要被拷貝到內存中運行。為了解決這個矛盾,盡可能的節約代碼在運行過程中變量所占用的內存空間,“堆棧”和“局部變量”這兩個概念就被提了出來。其中“局部變量”從軟件的角度指出了某些變量只需要在特定的時間段【生存期】存在于單片機的內存中即可滿足程序正確運行的要求,而“堆棧”則從硬件的角度為程序員控制局部變量的生存期提供了便利。
3. 堆棧的功能是怎么實現的?
說的那么玄乎,堆棧和局部變量到底是怎么減少內存占用的呢?
3.1 軟件的角度:
從功能實現的角度講,函數實參和局部變量其實都可以用全局變量來實現。 但隨之而來會有幾個問題/缺點:
全局變量在程序執行的整個周期都存在,占用了大量的內存空間。有的變量明明就只被某個函數調用。既然這樣,對于這種變量,我能不能在函數用的時候聲明,調用完了就把它的內存空間釋放掉,讓給別的函數來用,這樣不就大大提高了內存的利用率了嗎,要知道單片機的RAM是很寶貴的。 想到這里,局部變量的概念就被發明了,即這些變量的生存周期只需要和對應的函數相同即可
【額外好處:由于局部變量在函數里面生成,所以函數copy到別的工程里面還能直接用,想想如果你把函數要用的變量聲明在函數外,那你copy的時候還要特意去找,多麻煩】
3.2 硬件的角度:
想法非常好,當年的科學家也是這么想的,但是每次都手動的用匯編指令去創建,刪除變量好麻煩!程序員也是人啊,于是為了擺脫繁瑣的重復勞動,棧被發明了出來。棧并不是一個純粹抽象的軟件概念,而是由包括esp,ebp這些實際存在的堆棧寄存器來支撐的。
下面講解這兩個寄存器是如何將局部變量的創建和刪除自動化起來,從而節約了程序員大量時間的:
Esp寄存器:存儲棧頂地址
Ebp寄存器: 存儲棧基地址
Esp到ebp地址之間被視為當前函數的棧空間,聲明變量時,根據局部變量的大小,將堆棧寄存器esp的值下移,即可留出對應的空間用于存儲該變量。而刪除時,只需要將當前ebp的值賦給esp【即將棧頂指針直接壓倒棧底】,即可自動將所有與該函數相關的局部變量清空,將所占用空間釋放。一條指令,統一管理,統一釋放,美滋滋!
最后總結一下,在相較于上古時期手動創建,刪除全局變量來實現節約內存的無奈之舉,通過堆棧實現局部變量的管理有一下優點:
4. Reference:
http://c.biancheng.net/view/3634.html
總結
以上是生活随笔為你收集整理的c++堆栈溢出怎么解决_c语言进阶:堆栈原理揭秘的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: idea console中文乱码_ide
- 下一篇: 返回局部变量或临时变量的地址_C++的函