性无码一区二区三区在线观看,少妇被爽到高潮在线观看,午夜精品一区二区三区,无码中文字幕人妻在线一区二区三区,无码精品国产一区二区三区免费

程序小白
認(rèn)證:優(yōu)質(zhì)創(chuàng)作者
所在專題目錄 查看專題
不一樣的宏定義(C語(yǔ)言小知識(shí))
函數(shù)的調(diào)用和回調(diào)(OS小知識(shí))
C語(yǔ)言指針數(shù)組(C語(yǔ)言小知識(shí))
C語(yǔ)言中函數(shù)調(diào)用與堆棧詳解
被C標(biāo)準(zhǔn)和編譯器選項(xiàng)給狠狠的上了一課
extern "C" 的意義?——盤一下GCC!
作者動(dòng)態(tài) 更多
基于stm32采用PWM驅(qū)動(dòng)伺服控制器學(xué)習(xí)筆記
5天前
基于STM32驅(qū)動(dòng)TM1638學(xué)習(xí)筆記——軟件篇
04-19 12:42
基于TM1638驅(qū)動(dòng)8位數(shù)碼管設(shè)計(jì)分享
02-24 11:26
RT-Thread驅(qū)動(dòng)之路: Studio創(chuàng)建FAL分區(qū)⑤
01-02 08:30
RT-Thread驅(qū)動(dòng)之路: Studio 掛載通用SPI flash④
2024-12-23 13:41

C語(yǔ)言中函數(shù)調(diào)用與堆棧詳解

    

      為什么要了解C語(yǔ)言中函數(shù)調(diào)用與堆棧的關(guān)系?因?yàn)樵诓僮飨到y(tǒng)中,所有的上下文切換,其實(shí)就是都是關(guān)于系統(tǒng)棧和線程棧之間的數(shù)據(jù)交換,,要真正的理解棧,只有放在應(yīng)用中去看待它,函數(shù)的調(diào)用是棧最重要的應(yīng)用,其實(shí)函數(shù)還有個(gè)秘密,那就是它其實(shí)就是自成一界的上下文,是不是很神奇。

【堆棧篇】

棧也叫堆棧、他就是一種數(shù)據(jù)結(jié)構(gòu),以先入后出的方式進(jìn)行數(shù)據(jù)的存儲(chǔ)。

      在C語(yǔ)言中棧是非常重要的,以STM32為例,雖然芯片只能執(zhí)行機(jī)器指令,并且所有的語(yǔ)言都會(huì)被編譯成機(jī)器指令,但是不同語(yǔ)言編譯成機(jī)器指令的方式是不一樣的,也就是說(shuō)芯片是有運(yùn)行環(huán)境的,芯片的啟動(dòng)都是從啟動(dòng)文件開始的,也就是所謂的startup.s ,這個(gè)時(shí)候,他是在匯編環(huán)境中執(zhí)行的,然后他要切換到C語(yǔ)言環(huán)境,有一個(gè)最重要的事情,就是設(shè)置具體的堆棧結(jié)構(gòu)。

      然后你就可以執(zhí)行應(yīng)用C語(yǔ)言編寫的代碼了,那么堆棧的作用到底是什么?

      答案就是:為了完成函數(shù)的調(diào)用,棧主要用來(lái)存放函數(shù)參數(shù)、局部變量、返回值等等數(shù)據(jù)。

      如何來(lái)維護(hù)一個(gè)棧內(nèi)的數(shù)據(jù),是通過(guò)堆棧指針來(lái)實(shí)現(xiàn)的,主要涉及的esp棧頂指針、ebp棧底指針

      棧頂指針主要用來(lái)完成數(shù)據(jù)的進(jìn)棧和出棧操作。

      棧底指針主要用來(lái)查找當(dāng)前棧內(nèi)數(shù)據(jù)的位置,作為基地址參考。

【函數(shù)調(diào)用篇】

要完成一個(gè)函數(shù)的調(diào)用,CPU需要做些什么?

1.保存案發(fā)現(xiàn)場(chǎng)記錄。

2.給要調(diào)用的函數(shù)創(chuàng)建一塊空間,用于該函數(shù)執(zhí)行過(guò)程所產(chǎn)生的記錄。

3.函數(shù)調(diào)用執(zhí)行完成,返回到原有記錄。

簡(jiǎn)單的理解,函數(shù)調(diào)用就是需要保存一些相關(guān)的記錄,而這些記錄就被存在堆棧中。具體看看這個(gè)記錄里面都有哪些內(nèi)容(按順序記錄):

1.實(shí)際參數(shù)、返回地址、edp棧底指針首先入棧。

2.局部變量、形式參數(shù)、返回值入棧。

3.CPU運(yùn)行相關(guān)的寄存器進(jìn)棧。

關(guān)于函數(shù)調(diào)用入棧慣例

這里不具體介紹,有很多的標(biāo)準(zhǔn),

主要用于規(guī)定例如參數(shù)是自左至右入棧,還是自右至左入棧?等等。

感興趣可以問問度娘,看看都有哪些標(biāo)準(zhǔn)。

深入解析函數(shù)進(jìn)棧(出棧剛好相反過(guò)程)。

讓我用一段最簡(jiǎn)單的代碼來(lái)說(shuō)明關(guān)于函數(shù)調(diào)用而引發(fā)的堆棧操作

void MyCall(int a, int b)
{
	int p =11, q = 22;
}
int main(void)
{
	
	Mycall(33, 44);
	
	return 0;
}

跟著PC指針的位置來(lái)看一下堆棧在每一個(gè)時(shí)刻都是什么樣子,

未執(zhí)行調(diào)用函數(shù)時(shí),如下:

執(zhí)行Mycall函數(shù)入口,如下:

執(zhí)行函數(shù)函數(shù)體時(shí)棧記錄內(nèi)容,如下:

關(guān)于堆棧的內(nèi)容,其實(shí)還有溢出這一部分,太深了,太繞了,講不明白。。。

能力有限,留到以后慢慢研究吧。

關(guān)于棧溢出部分還是多多少少的提及一下,在我們的程序運(yùn)行進(jìn)入C語(yǔ)言環(huán)境之前,棧的大小就要被定義好,也就是棧的容量是有限的和固定的。

函數(shù)的調(diào)用會(huì)消耗棧內(nèi)存,函數(shù)的調(diào)用結(jié)束則會(huì)釋放占內(nèi)存,在我們實(shí)際應(yīng)用過(guò)程中,最大的潛在問題是函數(shù)的嵌套調(diào)用,因?yàn)樗粫?huì)進(jìn)行壓棧操作,不會(huì)彈棧操作,所以會(huì)導(dǎo)致棧內(nèi)存不斷被消耗,棧的內(nèi)存又是有限的,當(dāng)超過(guò)最大的限度時(shí)候,就會(huì)發(fā)生棧溢出錯(cuò)誤,程序可能異常退出或者死機(jī)等現(xiàn)象。

這時(shí)候可能就會(huì)有我們老工程師經(jīng)常給我們提的建議,函數(shù)嵌套不要太深,一般不要超過(guò)多少層,函數(shù)的內(nèi)部盡量不要用大的局部變量。

當(dāng)然我們也會(huì)想,那如果我們把棧定義的大點(diǎn)是不是就不用擔(dān)心棧溢出了?

但是你要知道棧定義消耗的是RAM的空間。

而你的單片機(jī)又有多少的RAM空間呢?

一般也就幾十KB吧

總要給應(yīng)用程序留一點(diǎn)空間去申請(qǐng)來(lái)完成程序功能啊,所以建議棧定義不要太大,給一個(gè)特定的大小就可以,剩下的就是想辦法減少函數(shù)嵌套的層數(shù)了。

關(guān)于棧的使用在PC機(jī)上又會(huì)出現(xiàn)其它的問題。

比如棧溢出攻擊。。。超綱了,有興趣的同學(xué)可以自行百度。

聲明:本內(nèi)容為作者獨(dú)立觀點(diǎn),不代表電子星球立場(chǎng)。未經(jīng)允許不得轉(zhuǎn)載。授權(quán)事宜與稿件投訴,請(qǐng)聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯(cuò)的朋友,別忘了一鍵三連哦!
贊 6
收藏 4
關(guān)注 150
成為作者 賺取收益
全部留言
0/200
成為第一個(gè)和作者交流的人吧