函數(shù)調(diào)用棧

對于程序傻谁,編譯器會為其分配一段內(nèi)存,在邏輯上可以分為代碼段列粪、數(shù)據(jù)段栅螟、堆、棧篱竭,而函數(shù)調(diào)用則是發(fā)生在棧上力图。
代碼段:保存程序文本,指令指針eip就是指向代碼段掺逼,可讀可執(zhí)行不可寫
數(shù)據(jù)段:保存初始化的全局變量和靜態(tài)變量吃媒,可讀可寫不可執(zhí)行
BSS:未初始化的全局變量和靜態(tài)變量
堆(Heap):動態(tài)分配內(nèi)存,向地址增大的方向增長,可讀可寫可執(zhí)行
棧(Stack):存放局部變量赘那,函數(shù)參數(shù)刑桑,當前狀態(tài),函數(shù)調(diào)用信息等募舟,向地址減小的方向增長祠斧,可讀可寫可執(zhí)行

相關(guān)寄存器

ebp:基址指針寄存器,存放當前函數(shù)棧幀的基地址
esp:堆棧(Stack)指針寄存器拱礁,存放當前函數(shù)棧幀的棧頂?shù)刂?eip: 指令寄存器琢锋,指向下一條指令的地址
exp:存放函數(shù)返回值

函數(shù)調(diào)用棧結(jié)構(gòu)圖


1025005-20160924105903152-717146733.gif

入棧過程

1、將調(diào)用者函數(shù)的ebp入棧
2呢灶、將調(diào)用者函數(shù)的棧頂指針esp賦值給被調(diào)用函數(shù)的ebp
3吴超、按從右到左的順序?qū)⒈徽{(diào)用函數(shù)的參數(shù)入棧
4、按聲明的順序?qū)⒈徽{(diào)用函數(shù)的局部變量入棧
5鸯乃、將調(diào)用函數(shù)的下一個指令地址作為返回地址入棧
6鲸阻、將被調(diào)用函數(shù)的第一條指令地址賦值給eip寄存器
7、開始執(zhí)行被調(diào)用函數(shù)指令

ebp寄存器處于一個非常重要的位置缨睡,該寄存器中存放的地址可以作為基準鸟悴,向棧底方向可以獲取返回地址,傳入?yún)?shù)值奖年,向棧頂方向可以獲取函數(shù)的局部變量细诸。而esp所指向的內(nèi)存中又存放著上一層函數(shù)調(diào)用的ebp值。

出棧過程

1拾并、將函數(shù)返回值存入eax寄存器中
2揍堰、執(zhí)行l(wèi)eave指令
3鹏浅、執(zhí)行ret指令

帶異承嵋澹回退的函數(shù)調(diào)用棧

棧展開

棧展開(unwinding)是指當前的try...catch...塊匹配成功或者匹配不成功異常對象后,從try塊內(nèi)異常對象的拋出位置隐砸,到try塊的開始處的所有已經(jīng)執(zhí)行了各自構(gòu)造函數(shù)的局部變量之碗,按照構(gòu)造生成順序的逆序,依次被析構(gòu)季希。如果當前函數(shù)內(nèi)對拋出的異常對象匹配不成功褪那,則從最外層的try語句到當前函數(shù)體的起始位置處的局部變量也依次被逆序析構(gòu),實現(xiàn)棧展開式塌,然后再回退到調(diào)用棧的上一層函數(shù)內(nèi)從函數(shù)調(diào)用點開始繼續(xù)處理該異常博敬。

catch語句如果匹配異常對象成功,在完成了對catch語句的參數(shù)的初始化(對傳值參數(shù)完成了參數(shù)對象的copy構(gòu)造)之后妆艘,對同層級的try塊執(zhí)行棧展開破加。

相關(guān)數(shù)據(jù)結(jié)構(gòu)


struct UNWINDTBL {

    int nNextIdx;

    void (*pfnDestroyer)(void *this);

    void    *pObj; 

};

struct CATCHBLOCK {

    //...



    type_info  *piType;

    void        *pCatchBlockEntry;

}

struct TRYBLOCK {

    //...

    int        nBeginStep;

    int    nEndStep;

    CATCHBLOCK  tblCatchBlocks[]; 

};

struct EHDL {

    //...



    UNWINDTBL  tblUnwind[];

    TRYBLOCK    tblTryBlocks[];



    //... 

};

struct EXP {

    EXP    *piPrev; //成員指向鏈表的上一個節(jié)點秸滴,它主要用于在函數(shù)調(diào)用棧中逐級向上尋找匹配的 catch 塊绳泉,并完成椉劳回退工作伦意。

    EHDL    *piHandler; //成員指向完成異常捕獲和棧回退所必須的數(shù)據(jù)結(jié)構(gòu)(主要是兩張記載著關(guān)鍵數(shù)據(jù)的表:“try”塊表:tblTryBlocks 及“椗鸩梗回退表”:tblUnwind)驮肉。

    int    nStep; //成員用來定位 try 塊,以及在椧押В回退表中尋找正確的入口离钝。

};

調(diào)用棧示意圖


1025005-20160924105930137-526226122.png

棧展開過程

nStep 變量用于跟蹤函數(shù)內(nèi)局部對象的構(gòu)造、析構(gòu)階段疾捍。再配合編譯器為每個函數(shù)生成的 tblUnwind 表奈辰,就可以完成退棧機制。表中的 pfnDestroyer 字段記錄了對應(yīng)階段應(yīng)當執(zhí)行的析構(gòu)操作(析構(gòu)函數(shù)指針)乱豆;pObj 字段則記錄了與之相對應(yīng)的對象 this 指針偏移奖恰。將 pObj 所指的偏移值加上當前棧框架基址(EBP)宛裕,就是要代入 pfnDestroyer 所指析構(gòu)函數(shù)的 this 指針瑟啃,這樣即可完成對該對象的析構(gòu)工作。而 nNextIdx 字段則指向下一個需要析構(gòu)對象所在的行(下標)揩尸。

在發(fā)生異常時蛹屿,異常處理器首先檢查當前函數(shù)棧框架內(nèi)的 nStep 值岩榆,并通過 piHandler 取得 tblUnwind[] 表错负。然后將 nStep 作為下標帶入表中,執(zhí)行該行定義的析構(gòu)操作勇边,然后轉(zhuǎn)向由 nNextIdx 指向的下一行犹撒,直到 nNextIdx 為 -1 為止。在當前函數(shù)的椓0回退工作結(jié)束后识颊,異常處理器可沿當前函數(shù)棧框架內(nèi) piPrev 的值回溯到異常處理鏈中的上一節(jié)點重復上述操作奕坟,直到所有回退工作完成為止祥款。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市月杉,隨后出現(xiàn)的幾起案子刃跛,更是在濱河造成了極大的恐慌,老刑警劉巖苛萎,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桨昙,死亡現(xiàn)場離奇詭異跌帐,居然都是意外死亡,警方通過查閱死者的電腦和手機绊率,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門谨敛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人滤否,你說我怎么就攤上這事脸狸。” “怎么了藐俺?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵炊甲,是天一觀的道長。 經(jīng)常有香客問我欲芹,道長卿啡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任菱父,我火速辦了婚禮颈娜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘浙宜。我一直安慰自己官辽,他們只是感情好,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布粟瞬。 她就那樣靜靜地躺著同仆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪裙品。 梳的紋絲不亂的頭發(fā)上俗批,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機與錄音市怎,去河邊找鬼岁忘。 笑死,一個胖子當著我的面吹牛焰轻,可吹牛的內(nèi)容都是我干的臭觉。 我是一名探鬼主播昆雀,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼辱志,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了狞膘?” 一聲冷哼從身側(cè)響起揩懒,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挽封,沒想到半個月后已球,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年智亮,在試婚紗的時候發(fā)現(xiàn)自己被綠了忆某。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡阔蛉,死狀恐怖弃舒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情状原,我是刑警寧澤聋呢,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站颠区,受9級特大地震影響削锰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜毕莱,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一器贩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧朋截,春花似錦磨澡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至饲宿,卻和暖如春厦酬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瘫想。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工仗阅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人国夜。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓减噪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親车吹。 傳聞我的和親對象是個殘疾皇子筹裕,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 原文地址:C語言函數(shù)調(diào)用棧(一)C語言函數(shù)調(diào)用棧(二) 0 引言 程序的執(zhí)行過程可看作連續(xù)的函數(shù)調(diào)用。當一個函數(shù)執(zhí)...
    小豬啊嗚閱讀 4,616評論 1 19
  • 棧: 在函數(shù)調(diào)用時窄驹,第一個進棧的是主函數(shù)中函數(shù)調(diào)用后的下一條指令(函數(shù)調(diào)用語句的下一條可執(zhí)行語句)的地址朝卒,然后是函...
    zjfclimin閱讀 4,001評論 0 5
  • 還有82天就是研究生入學考試了。 關(guān)于英語語言文學要考的是四科乐埠,沒有一科拿得出手抗斤。都知道考研的每個人都不容...
    學語言的汪閱讀 119評論 0 1
  • 去年底囚企,與戰(zhàn)友聊天,無意中談起“阿冰”瑞眼。 不久龙宏,朋友圈里傳來“阿冰與原勤務(wù)隊XXX戀愛了”的消息。 又過了一段時間...
    春嘩秋拾閱讀 503評論 0 4
  • 之前看過《不安的時候伤疙,坐下來寫》烦衣,當時還寫了10條清單,之后卻沒有再次全文閱讀過了掩浙。 而在書中花吟,到目前為止還記得的...
    雪晴_雪晴閱讀 306評論 0 2