C C 函式呼叫, 棧的大小是如何被確定的

2021-06-09 05:59:19 字數 1708 閱讀 9980

每個函式呼叫都要壓棧, 

棧用來存放區域性變數和形參以及狀態指標,

可是很多時候變數是按程式邏輯動態建立的, 編譯器不可能知道函式塊需要多少區域性變數啊?

比如這樣乙個函式: 

void test()

else // 棧的大小應按sizeof(a) 還是 sizeof(b)計算? 

_test    proc

;line 2

push

ebp

movebp, esp

subesp, 12;

0000000ch

................

;line 13

movesp, ebp

popebp

ret0

_test endp

編譯器需要知道區域性變數所需的總空間,即所有區域性變數所需空間的和。樓主的例子裡就是8+4=12

void

test()

push

ebp //*儲存caller的frame基址, push操作會使棧頂暫存器esp位址前移4bytes

movebp,esp //*原棧頂變為新frame的基址,因而棧是連續的

addesp,-

0x08

//*棧頂前移8 bytes, 預留變數a,b的空間,這證明frame的大小的確是編譯時確定的.

mov[ebp-

0x04

],0x00000001

//*區域性變數a賦值1

mov[ebp-

0x08

],0x00000002

//*區域性變數b賦值2

popecx //這個不明白了, ecx計數暫存器, 在這pop它幹啥????

popecx // ????而且還pop兩次?????

popebp //*恢復caller的frame基址

ret//*返回

函式呼叫的確是是個壓棧的過程; 函式返回後,壓棧的資料被彈出。

棧的大小,應該由編譯器和os共同決定吧。

編譯器中,有frame 和 record的概念。來控制函式呼叫和返回。以及發生異常時,棧的回退(unwinded)等。

函式呼叫中其相關資訊和其區域性變數的空間都在棧上分配,而且是編譯器自動分配。

至於你說的是sizeof(a) 還是sizeof(b);個人覺得應該大於sizeof(a) + sizeof(b);

因為函式呼叫的過程,是乙個上下文切換的過程,其間,首先要儲存現場、然後將函式的返回位址及區域性變數壓棧、執行函式、返回、恢復現場。 如果寫過匯程式設計序,這個就很容易理解了。

這些都是有編譯器實現的,具體細節我們不必關心。

alloc 可以在棧上分配記憶體。你可以通過在函式內部定義乙個足夠大陣列,來看看,你的編譯器分配的stack size。

現代系統,都是乙個執行緒乙個棧,所以叫做執行緒棧,windows預設乙個執行緒1mb的棧,每新開乙個執行緒,就配套分配1mb的棧,當然也可以指定大小

注意區分兩種存在方式:乙個是在檔案裡,乙個是在虛擬記憶體裡

靜態和全域性變數儲存在.exe/.dll檔案的資料區,執行時則被載入到虛擬記憶體的某個區域,既不在堆,也不在棧

區域性變數實質上是以**的形式,即相關的push/pop指令,儲存在.exe/.dll檔案的**區,執行時,**被載入到虛擬記憶體的某個區。而執行**裡的push/pop時,區域性變數被壓入/彈出棧

乙個c c 函式呼叫棧的實現

函式呼叫棧的實現。可用於實現簡單的指令碼直譯器。宣告 pragma once const int buffersize 1024 const int growfactor 2 this stack is used as call stack.class tstack push an int void...

matlab中如何檢視被呼叫函式的變數

相信用過matlab的小夥伴們都知道,在介面右側的工作區中可以看到主程式中呼叫的變數,那麼如何看主程式中呼叫的函式的變數呢?其實也很簡單啦,我們可以這麼做 1 將主程式中函式末尾的分號去掉,再次執行程式,在命令列窗 們就可以看到函式中自變數的值 然而,被呼叫函式的程式中的一些變數 常量的值我們如何知...

free 函式是如何知曉記憶體塊大小的?

想要理解這個問題,必須先要了解一下malloc函式的實現。首先在程式執行時,系統會為它分配4g的虛擬記憶體,其中就包括堆 heap 堆是可在執行時 為變數 動態進行記憶體分配的一塊區域,堆頂端稱作program break。malloc分配的記憶體允許隨意釋放,它們被維護於一張空閒記憶體列表中,在後...