C++程序的內(nèi)存布局

轉(zhuǎn)載聲明:http://blog.csdn.net/imyfriend/article/details/8497103。
imyfriend的專欄 感謝原作者的支持!

對(duì)任何一個(gè)普通C++程序來(lái)講,它都會(huì)涉及到5種不同的數(shù)據(jù)段。常用的幾個(gè)數(shù)據(jù)段種包含有“程序代碼段”、“程序數(shù)據(jù)段”、“程序堆棧段”等。不錯(cuò),這幾種數(shù)據(jù)段都在其中,但除了以上幾種數(shù)據(jù)段之外,進(jìn)程還另外包含兩種數(shù)據(jù)段。下面我們來(lái)簡(jiǎn)單歸納一下進(jìn)程對(duì)應(yīng)的內(nèi)存空間中所包含的5種不同的數(shù)據(jù)區(qū)。

示意圖.jpeg

代碼段:代碼段是用來(lái)存放可執(zhí)行文件的操作指令,也就是說(shuō)是它是可執(zhí)行程序在內(nèi)存種的鏡像。代碼段需要防止在運(yùn)行時(shí)被非法修改,所以只準(zhǔn)許讀取操作,而不允許寫入(修改)操作——它是不可寫的。
數(shù)據(jù)段:數(shù)據(jù)段用來(lái)存放可執(zhí)行文件中已初始化全局變量,換句話說(shuō)就是存放程序靜態(tài)分配的變量和全局變量。
BSS段:BSS段包含了程序中未初始化全局變量,在內(nèi)存中bss段全部置零。
堆(heap):堆是用于存放進(jìn)程運(yùn)行中被動(dòng)態(tài)分配的內(nèi)存段,它大小并不固定,可動(dòng)態(tài)擴(kuò)張或縮減。當(dāng)進(jìn)程調(diào)用malloc/new等函數(shù)分配內(nèi)存時(shí),新分配的內(nèi)存就被動(dòng)態(tài)添加到堆上(堆被擴(kuò)張);當(dāng)利用free等函數(shù)釋放內(nèi)存時(shí),被釋放的內(nèi)存從堆中被剔除(堆被縮減)
棧:棧是用戶存放程序臨時(shí)創(chuàng)建的局部變量,也就是說(shuō)我們函數(shù)括弧“{}”中定義的變量(但不包括static聲明的變量,static意味這在數(shù)據(jù)段中存放變量)。除此以外在函數(shù)被調(diào)用時(shí),其參數(shù)也會(huì)被壓入發(fā)起調(diào)用的進(jìn)程棧中,并且待到調(diào)用結(jié)束后,函數(shù)的返回值也回被存放回棧中。由于棧的先進(jìn)先出特點(diǎn),所以棧特別方便用來(lái)保存/恢復(fù)調(diào)用現(xiàn)場(chǎng)。從這個(gè)意義上將我們可以把堆??闯梢粋€(gè)臨時(shí)數(shù)據(jù)寄存、交換的內(nèi)存區(qū)。

示意圖2.jpeg

我們要知道,棧中存放的是一個(gè)個(gè)被調(diào)函數(shù)所對(duì)應(yīng)的堆棧幀,當(dāng)函數(shù)fun1被調(diào)用,則fun1的堆棧幀入棧,fun1返回時(shí),fun1的堆棧幀出棧。什么是堆棧幀呢,堆棧幀其實(shí)就是保存被調(diào)函數(shù)返回時(shí)下一條執(zhí)行指令的指針、主調(diào)函數(shù)的堆棧幀的指針、主調(diào)函數(shù)傳遞給被調(diào)函數(shù)的實(shí)參(如果有的話)、被調(diào)函數(shù)的局部變量等信息的一個(gè)結(jié)構(gòu)。
首先,我們要說(shuō)明的是如何區(qū)分每個(gè)堆棧幀,或者說(shuō),如何知道我現(xiàn)在在使用哪個(gè)堆棧幀。和棧密切相關(guān)的有2個(gè)寄存器,一個(gè)是ebp,一個(gè)是esp,前者可以叫作?;分羔?,后者可以叫棧頂指針。對(duì)于一個(gè)堆棧幀來(lái)說(shuō),ebp也叫堆棧幀指針,它永遠(yuǎn)指向這個(gè)堆棧幀的某個(gè)固定位置(見(jiàn)上圖),所以可以根據(jù)ebp來(lái)表示一個(gè)堆棧幀,可以通過(guò)對(duì)ebp的偏移加減,來(lái)在堆棧幀中來(lái)來(lái)回回的訪問(wèn)。esp則是隨著push和pop而不斷移動(dòng)。因此根據(jù)esp來(lái)對(duì)堆棧幀進(jìn)行操作。
再來(lái)講一下上圖,一個(gè)堆棧幀的最頂部,是實(shí)參,然后是return address,這個(gè)值是由主調(diào)函數(shù)中的call命令在call調(diào)用時(shí)自動(dòng)壓入的,不需要我們關(guān)心,previousframe pointer,就是主調(diào)函數(shù)的堆棧幀指針,也就是主調(diào)函數(shù)的ebp值。ebp偏移為正的都是被調(diào)函數(shù)的局部變量。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容