十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
今天就跟大家聊聊有關(guān)什么是C++的堆棧指引,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

我們經(jīng)常會(huì)討論這樣的問題:什么時(shí)候數(shù)據(jù)存儲(chǔ)在堆棧(Stack)中,什么時(shí)候數(shù)據(jù)存儲(chǔ)在堆(Heap)中。我們知道,局部變量是存儲(chǔ)在堆棧中的;debug時(shí),查看堆棧可以知道函數(shù)的調(diào)用順序;函數(shù)調(diào)用時(shí)傳遞參數(shù),事實(shí)上是把參數(shù)壓入堆棧,聽起來,堆棧象一個(gè)大雜燴。那么,堆棧(Stack)到底是如何工作的呢?本文將詳解C/C++堆棧的工作機(jī)制。閱讀時(shí)請(qǐng)注意以下幾點(diǎn):
1)本文討論的編譯環(huán)境是VisualC/C++,由于高級(jí)語言的堆棧工作機(jī)制大致相同,因此對(duì)其他編譯環(huán)境或高級(jí)語言如C#也有意義。
2)本文討論的堆棧,是指程序?yàn)槊總€(gè)線程分配的默認(rèn)堆棧,用以支持程序的運(yùn)行,而不是指程序員為了實(shí)現(xiàn)算法而自己定義的堆棧。
3)本文討論的平臺(tái)為intelx86。
4)本文的主要部分將盡量避免涉及到匯編的知識(shí),在本文最后可選章節(jié),給出前面章節(jié)的反編譯代碼和注釋。
5)結(jié)構(gòu)化異常處理也是通過堆棧來實(shí)現(xiàn)的(當(dāng)你使用try…catch語句時(shí),使用的就是c++對(duì)windows結(jié)構(gòu)化異常處理的擴(kuò)展),但是關(guān)于結(jié)構(gòu)化異常處理的主題太復(fù)雜了,本文將不會(huì)涉及到。
1)程序的堆棧是由處理器直接支持的。在intelx86的系統(tǒng)中,堆棧在內(nèi)存中是從高地址向低地址擴(kuò)展(這和自定義的堆棧從低地址向高地址擴(kuò)展不同),因此,棧頂?shù)刂肥遣粩鄿p小的,越后入棧的數(shù)據(jù),所處的地址也就越低。
2)在32位系統(tǒng)中,堆棧每個(gè)數(shù)據(jù)單元的大小為4字節(jié)。小于等于4字節(jié)的數(shù)據(jù),比如字節(jié)、字、雙字和布爾型,在堆棧中都是占4個(gè)字節(jié)的;大于4字節(jié)的數(shù)據(jù)在堆棧中占4字節(jié)整數(shù)倍的空間。
3)和堆棧的操作相關(guān)的兩個(gè)寄存器是EBP寄存器和ESP寄存器的,本文中,你只需要把EBP和ESP理解成2個(gè)指針就可以了。ESP寄存器總是指向堆棧的棧頂,執(zhí)行PUSH命令向堆棧壓入數(shù)據(jù)時(shí),ESP減4,然后把數(shù)據(jù)拷貝到ESP指向的地址;執(zhí)行POP命令時(shí),首先把ESP指向的數(shù)據(jù)拷貝到內(nèi)存地址/寄存器中,然后ESP加4。EBP寄存器是用于訪問堆棧中的數(shù)據(jù)的,它指向堆棧中間的某個(gè)位置(具體位置后文會(huì)具體講解),函數(shù)的參數(shù)地址比EBP的值高,而函數(shù)的局部變量地址比EBP的值低,因此參數(shù)或局部變量總是通過EBP加減一定的偏移地址來訪問的,比如,要訪問函數(shù)的第一個(gè)參數(shù)為EBP+8。
4)堆棧中到底存儲(chǔ)了什么數(shù)據(jù)?包括了:函數(shù)的參數(shù),函數(shù)的局部變量,寄存器的值(用以恢復(fù)寄存器),函數(shù)的返回地址以及用于結(jié)構(gòu)化異常處理的數(shù)據(jù)(當(dāng)函數(shù)中有try…catch語句時(shí)才有,本文不討論)。這些數(shù)據(jù)是按照一定的順序組織在一起的,我們稱之為一個(gè)堆棧幀(StackFrame)。一個(gè)堆棧幀對(duì)應(yīng)一次函數(shù)的調(diào)用。在函數(shù)開始時(shí),對(duì)應(yīng)的堆棧幀已經(jīng)完整地建立了(所有的局部變量在函數(shù)幀建立時(shí)就已經(jīng)分配好空間了,而不是隨著函數(shù)的執(zhí)行而不斷創(chuàng)建和銷毀的);在函數(shù)退出時(shí),整個(gè)函數(shù)幀將被銷毀。
5)在文中,我們把函數(shù)的調(diào)用者稱為caller(調(diào)用者),被調(diào)用的函數(shù)稱為callee(被調(diào)用者)。之所以引入這個(gè)概念,是因?yàn)橐粋€(gè)函數(shù)幀的建立和清理,有些工作是由Caller完成的,有些則是由Callee完成的。
看完上述內(nèi)容,你們對(duì)什么是C++的堆棧指引有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。