函數調用堆棧


熟悉掌握c++中函數調用堆棧,內存管理,智能指針

c++如何在程序運行時為程序調用內核堆棧的呢?

CPU是如何識別被調參數的呢?怎么保存傳遞的參數的呢?

所以cpu引進了棧的數據結構來完成函數的調用,函數調用時依次把參數壓棧,然后調用函數,

調用完以后從堆棧中取出數據並計算,計算結束后清棧

回想這個時先回想一下虛擬空間的空間布局和調用約定

int sumint aint b

{

  int tmp=0;

tmp=a+b;

return tmp;

}

int main()

{

  int a=10;

int b=20;

 int ret=0;

ret=sum(a,b);

Printf(“%d”,ret);

}

虛擬空間內存布局:1G內核空間,3G用戶空間

保留區  128M 不可讀不可寫

0x00000000

--

0x0804 8000

.text 指令

 

.data

 

.bss未初始化

(執行前清0

heap

向下開辟 

共享庫

 

stack 棧   

向上開辟 

環境變量

0xc000 0000

DMA

 

NORMAL

 

HIGHMEM

0xffff ffff

 

 

函數調用的具體情況:

Push 壓棧,pop 出棧,eaxebx:存放數值

ebp:棧底指針寄存器esp:棧頂指針寄存器call:壓入下一行的指令地址

返回值:4字節 eax帶出,8 eax  edx  8 用臨時量帶回(在調用方棧幀開辟,臨時量在形參壓棧后壓棧)

具體實現如下:

0x0000 0000             esp

tmp

main函數的棧底指針     ebp

下一條指令的地址 (&&printf

eax  10

eax  20

X X X X X X X X X X

ret   0

b    10

a    20

mainCRTstartup函數的棧底指針

 

 

關於四種調用約定:

參數的傳遞中有兩個問題需要明確 約定符號的生成,形參的入棧順序(pasclcall),形參的開辟和清理方式

_cdeclc標准調用約定      調用方開辟,調用方清除 如上

_stdcallwindows標准調用約定   自右向左入棧 調用方開辟,被調用方清除

_fastcall:快速調用約定   形參不開辟 在寄存器中存放 若形參個數過多的情況則

1)形參字節小於等於4  前兩個形參不開辟內存寄存器帶入被調用方 第三個開始和_stdcall調用約定相同

2)形參字節數大於4 和——stdcall相同,調用方開辟,被調用方清理

 

_thiscallc++成員方法的調用約定 ,對參數個數不定的 調用者清棧,否則函數自己清棧

//匯編太麻煩了,你們可以自己去看看

c++是如何管理內存的呢?

大家都知道c語言在管理內存時候的方式:即上圖;其實c++的內存管理也是如此

那就說一下c++的幾種存儲結構吧(堆,棧,全局/靜態存儲區,文字常量區,text段)

棧:局部變量,參數,編譯器自動開辟釋放,相當於計算機系統的數據結構分配專門的寄存器來存儲棧的地址,所以效率較高,內存空間連續,但由於向下開辟,空間有限

堆:手動開辟釋放,向上開辟,內存空間無限制,內存不連續,會有內存碎片產生,具體的newmalloc以后會具體說明

全局/靜態存儲區:全局變量,靜態變量,程序結束時自動釋放,包括data段和bass

文字常量區:存放在data

text段:存放程序的二進制代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM