RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C語(yǔ)言函數(shù)調(diào)用過(guò)程中的內(nèi)存變化解析

電子設(shè)計(jì) ? 來(lái)源:TOMORROW 星辰 ? 作者:TOMORROW 星辰 ? 2020-12-11 16:21 ? 次閱讀

相信很多編程新手村的同學(xué)們都會(huì)有一個(gè)疑問(wèn):C 語(yǔ)言如何調(diào)用函數(shù)的呢?局部變量的作用域?yàn)槭裁磧H限于函數(shù)內(nèi)?這個(gè)調(diào)用不是指C 語(yǔ)言上的函數(shù)調(diào)用的語(yǔ)法,而是在內(nèi)存的視角下,函數(shù)的調(diào)用過(guò)程。本文將從C 語(yǔ)言調(diào)用實(shí)例,內(nèi)存視角,反匯編代碼來(lái)探討C 語(yǔ)言函數(shù)的調(diào)用過(guò)程,也可以說(shuō)是C 語(yǔ)言函數(shù)調(diào)用過(guò)程圖解。通過(guò)這個(gè)C 語(yǔ)言函數(shù)調(diào)用過(guò)程圖解,同學(xué)們將會(huì)知道,C 語(yǔ)言函數(shù)在調(diào)用時(shí),內(nèi)存空間是怎樣變化的。

要想理解這一個(gè)過(guò)程還好涉及到函數(shù)棧幀的概念。函數(shù)棧幀指的是,在調(diào)用函數(shù)時(shí),系統(tǒng)在??臻g中給函數(shù)所分配的一段連續(xù)空間。其中 ebp(棧幀基址指針)則是指明了當(dāng)前函數(shù)的棧幀基地址,對(duì)函數(shù)的資源(局部變量、實(shí)參等)的訪問(wèn),都要通過(guò) ebp+offset(偏移量)來(lái)進(jìn)行訪問(wèn)。而 esp 則是棧指針,指示當(dāng)前??臻g棧頂?shù)奈恢谩?/p>

以下代碼即是此次探討 C 語(yǔ)言函數(shù)調(diào)用過(guò)程的實(shí)例源碼:

intsubFunc(intabc)
{
intdef=0x9999;
abc=0x8888;
returnabc;
}

int_tmain()
{

subFunc(0x2222);

return0;
}

源碼很簡(jiǎn)單,在一個(gè)主函數(shù)中,調(diào)用一個(gè)帶參數(shù)的子函數(shù)。源碼使用 Visual Studio2010 進(jìn)行調(diào)試,并同時(shí)查看內(nèi)存窗口、反匯編窗口及變量窗口。

進(jìn)入調(diào)試模式,并將斷點(diǎn)定在調(diào)用子函數(shù) subFunc()處,然后運(yùn)行并觀察。

通過(guò)觀察窗口,可以知道,此時(shí)還是在執(zhí)行 main 函數(shù),而 ebp(棧幀基址指針)指向的是 0x0073fb64,esp=0x0073fa98。從反匯編代碼可以看到,在調(diào)用函數(shù)前,需要先將參數(shù)壓棧,也就是將實(shí)參存到了 0x0073fa94 處,然后再調(diào)用到子函數(shù)。

進(jìn)入到子函數(shù)時(shí),esp 已經(jīng)變成了 0x0073fa8c,而 0x0073fa90 處存放的是,子函數(shù)執(zhí)行完后返回到 main 函數(shù)中的地址。進(jìn)入到子函數(shù)后,先將 main 函數(shù)的 ebp 壓棧,然后將當(dāng)前棧頂指針的值賦值給 ebp 作為當(dāng)前子函數(shù)的 subFunc()的棧幀基址指針。此時(shí) esp 和 ebp 都變成了 0x0073fa8c。

緊接著,可以看到,esp 一下子被減去了 0x0cch,也就是說(shuō)棧空間一下子增長(zhǎng)了 0x0cch,并且這段空間全部被賦值為 0xcc。再往下看,可以看到子函數(shù)中的局部變量被分配在了 0x0073fa84 處(因?yàn)樽兞渴?32 位的,然后 CPU 卻是 64 位的,所以空了 32 位不作使用),也就是說(shuō),這一段被初始化為 0xcc 的棧空間是被用來(lái)給局部變量分配空間的。

接下來(lái)再看,在 main 函數(shù)傳遞了一個(gè)實(shí)參 0x2222 給子函數(shù) subFunc 中的形參 abc。在對(duì) abc 進(jìn)行讀寫(xiě)時(shí),其實(shí)就是在對(duì)前面實(shí)參所被存儲(chǔ)的空間進(jìn)行讀寫(xiě),也就是說(shuō)形參在作為參數(shù)也作為局部變量的同時(shí),它所被分配的內(nèi)存空間是在函數(shù)棧幀基址 ebp 之下。

而子函數(shù)被執(zhí)行完后,返回的過(guò)程則是一個(gè)與上面過(guò)程相逆的過(guò)程。將相應(yīng)的數(shù)據(jù)出棧,恢復(fù) ebp 等信息,釋放子函數(shù)的??臻g,返回到主函數(shù)。所以局部變量的作用域只是在函數(shù)中,當(dāng)函數(shù)被執(zhí)行完返回時(shí),函數(shù)的棧幀都被釋放了,局部變量等數(shù)據(jù)也就沒(méi)有了,不存在了,也就是說(shuō)局部變量的生命周期是與函數(shù)的生命周期等同的。

經(jīng)過(guò)以上的 C 語(yǔ)言函數(shù)調(diào)用過(guò)程圖解,相信已經(jīng)理解了 C 語(yǔ)言在內(nèi)存中是如何調(diào)用的了。然后可以總結(jié)并得出下面的函數(shù)調(diào)用的棧幀圖解。從函數(shù)調(diào)用的層面看,棧空間是被從下往上一塊一塊地增長(zhǎng)的,并且是后分配的先被釋放,先分配的后被釋放。

編輯:hfy

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3019

    瀏覽量

    74003
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7604

    瀏覽量

    136688
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    C語(yǔ)言使用函數(shù)調(diào)用的知識(shí)點(diǎn)

    C語(yǔ)言使用函數(shù)調(diào)用,我們?cè)偈煜げ贿^(guò)了,但是函數(shù)調(diào)用在內(nèi)存
    發(fā)表于 09-07 11:47 ?829次閱讀

    C語(yǔ)言內(nèi)存知識(shí)總結(jié):memset函數(shù)和calloc函數(shù)

    memset(翻譯:清零)是計(jì)算機(jī)C/C++語(yǔ)言初始化函數(shù)。作用是將某一塊內(nèi)存
    發(fā)表于 10-24 10:40 ?1124次閱讀

    C函數(shù)調(diào)用機(jī)制與棧幀原理詳解

    當(dāng)一個(gè)C函數(shù)調(diào)用時(shí),函數(shù)的參數(shù)如何傳遞、堆棧指針如何變化、棧幀是如何被建立以及如何被消除的,一直缺乏系統(tǒng)性的理解,因此決定花時(shí)間學(xué)習(xí)下
    發(fā)表于 06-08 10:49 ?1289次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>函數(shù)</b><b class='flag-5'>調(diào)用</b>機(jī)制與棧幀原理詳解

    ARM函數(shù)調(diào)用過(guò)程說(shuō)明

    ARM函數(shù)調(diào)用默認(rèn)4個(gè)參數(shù)用R0-R4傳遞,大于4個(gè)用堆棧傳遞,局部變量保存在堆棧,下面以一個(gè)簡(jiǎn)單的函數(shù)來(lái)說(shuō)明這個(gè)過(guò)程。先定義
    發(fā)表于 04-26 10:05

    ARMv8的函數(shù)調(diào)用棧是什么意思?調(diào)用棧的內(nèi)存管理是怎樣的

    調(diào)用解析概念: 任意體系結(jié)構(gòu)的CPU,都設(shè)計(jì)了一套通用寄存器、狀態(tài)寄存器及其他控制寄存器,用以維系系統(tǒng)的正常運(yùn)行。函數(shù)調(diào)用過(guò)程中,CPU一般都需要處理幾件事情:保存母
    發(fā)表于 05-13 10:36

    C++教程之函數(shù)的遞歸調(diào)用

    C++教程之函數(shù)的遞歸調(diào)用 在執(zhí)行函數(shù) f 的過(guò)程中,又要調(diào)用 f
    發(fā)表于 05-15 18:00 ?35次下載

    C語(yǔ)言入門(mén)教程-malloc函數(shù)和free函數(shù)

    malloc函數(shù)和free函數(shù) 假設(shè)您的程序在執(zhí)行過(guò)程中需要分配一定量的內(nèi)存。您可以隨時(shí)調(diào)用malloc
    發(fā)表于 07-29 11:58 ?4649次閱讀

    C語(yǔ)言回調(diào)函數(shù)學(xué)習(xí)

    對(duì)指針的應(yīng)用是C語(yǔ)言編程的精髓所在,而回調(diào)函數(shù)就是C語(yǔ)言里面對(duì)函數(shù)指針的高級(jí)應(yīng)用。簡(jiǎn)而言之,回調(diào)
    發(fā)表于 05-27 09:44 ?7204次閱讀

    系統(tǒng)調(diào)用函數(shù)庫(kù)分析及實(shí)例

    作為用戶我們極少接觸系統(tǒng)調(diào)用,但是我們熟悉C 語(yǔ)言,對(duì)庫(kù)函數(shù)調(diào)用并不陌生。C
    發(fā)表于 06-23 16:46 ?46次下載
    系統(tǒng)<b class='flag-5'>調(diào)用</b><b class='flag-5'>函數(shù)</b>庫(kù)分析及實(shí)例

    使用過(guò)程仿真函數(shù)模擬PID控制的過(guò)程

    設(shè)定循環(huán)時(shí)間為200ms。例如OB31 2) 在OB31調(diào)用PID函數(shù)PID_compact,然后在全局庫(kù)打開(kāi)庫(kù)文件《Sim_controllprocess_V13_SP1》,并
    的頭像 發(fā)表于 05-27 17:31 ?3884次閱讀

    C語(yǔ)言代碼調(diào)用匯編函數(shù)需要注意什么

    來(lái)看下混合語(yǔ)言工程,就比如在匯編程序調(diào)用C函數(shù),或者在C
    的頭像 發(fā)表于 11-12 11:04 ?2820次閱讀

    C語(yǔ)言使用函數(shù)調(diào)用在內(nèi)存究竟發(fā)生了什么?

    C語(yǔ)言使用函數(shù)調(diào)用,我們?cè)偈煜げ贿^(guò)了,但是函數(shù)調(diào)用在內(nèi)存
    的頭像 發(fā)表于 01-13 14:09 ?1164次閱讀

    RPC如何在遠(yuǎn)程過(guò)程中調(diào)用?

    RPC(Remote Procedure Call Protocol)即遠(yuǎn)程過(guò)程調(diào)用,也就是調(diào)用函數(shù)是在其它的控制板上運(yùn)行的,不需要理會(huì)底層的通訊協(xié)議。
    的頭像 發(fā)表于 02-07 09:52 ?897次閱讀
    RPC如何在遠(yuǎn)程<b class='flag-5'>過(guò)程中</b><b class='flag-5'>調(diào)用</b>?

    C語(yǔ)言函數(shù)調(diào)用的形式及過(guò)程

    C語(yǔ)言函數(shù)調(diào)用時(shí)的數(shù)據(jù)傳遞 在調(diào)用有參函數(shù)時(shí),主調(diào)函數(shù)
    的頭像 發(fā)表于 03-10 14:28 ?1733次閱讀

    什么是函數(shù)調(diào)用?

    函數(shù)調(diào)用,就是使用我們已經(jīng)定義好的函數(shù),或者C語(yǔ)言自帶的庫(kù)函數(shù)。
    的頭像 發(fā)表于 04-04 17:21 ?5811次閱讀
    RM新时代网站-首页