如何利用C語(yǔ)言中的setjmp和longjmp實(shí)現(xiàn)異常捕獲和協(xié)程?
這是道哥的第 017 篇原創(chuàng)
一、前言
二、函數(shù)語(yǔ)法介紹
與 goto 語(yǔ)句比較
與 fork 函數(shù)比較
與 Python 語(yǔ)言中的 yield/resume 比較
三、利用 setjmp/longjmp 實(shí)現(xiàn)異常捕獲
四、利用 setjmp/longjmp 實(shí)現(xiàn)協(xié)程
五、總結(jié)
一、前言
在 C 標(biāo)準(zhǔn)庫(kù)中,有兩個(gè)威力很猛的函數(shù):setjmp 和 longjmp,不知道各位小伙伴在代碼中是否使用過(guò)?我問(wèn)了身體的幾位同事,一部分人不認(rèn)識(shí)這兩個(gè)函數(shù),有一部分人知道這個(gè)函數(shù),但從來(lái)沒(méi)有使用過(guò)。
從知識(shí)點(diǎn)范圍來(lái)看,這兩個(gè)函數(shù)的功能比較單純,一個(gè)簡(jiǎn)單的示例代碼就能說(shuō)清楚了。但是,我們需要從這個(gè)知識(shí)點(diǎn)進(jìn)行發(fā)散、思考,在不同的維度上,把這個(gè)知識(shí)點(diǎn)與這個(gè)編程語(yǔ)言中其它類(lèi)似的知識(shí)進(jìn)行聯(lián)想、對(duì)比;與其他編程語(yǔ)言中類(lèi)似的概念進(jìn)行比較;然后再思考這個(gè)知識(shí)點(diǎn)可以使用在哪些場(chǎng)合,別人是怎么來(lái)使用它的。
今天,我們就來(lái)掰扯掰扯這兩個(gè)函數(shù)。雖然在一般的程序中使用不上,但是在今后的某個(gè)場(chǎng)合,當(dāng)你需要處理一些比較奇特的程序流程時(shí),也許它們可以給你帶來(lái)意想不到的效果。
例如:我們會(huì)把 setjmp/longjmp 與 goto 語(yǔ)句進(jìn)行功能上的比較;與 fork 函數(shù)從返回值上進(jìn)行類(lèi)比;與 Python/Lua 語(yǔ)言中的協(xié)程進(jìn)行使用場(chǎng)景上的比較。
二、函數(shù)語(yǔ)法介紹
1. 最簡(jiǎn)示例
先不講道理,直接看一下這個(gè)最簡(jiǎn)單的示例代碼,看不懂也沒(méi)關(guān)系,混個(gè)臉熟:
int main(){ // 一個(gè)緩沖區(qū),用來(lái)暫存環(huán)境變量 jmp_buf buf; printf("line1 "); // 保存此刻的上下文信息 int ret = setjmp(buf); printf("ret = %d ", ret); // 檢查返回值類(lèi)型 if (0 == ret) { // 返回值0:說(shuō)明是正常的函數(shù)調(diào)用返回 printf("line2 "); // 主動(dòng)跳轉(zhuǎn)到 setjmp 那條語(yǔ)句處 longjmp(buf, 1); } else { // 返回值非0:說(shuō)明是從遠(yuǎn)程跳轉(zhuǎn)過(guò)來(lái)的 printf("line3 "); } printf("line4 "); return 0;}
執(zhí)行結(jié)果:
執(zhí)行順序如下(如果不明白就不要深究,看完下面的解釋再回過(guò)頭來(lái)看):
2. 函數(shù)說(shuō)明
首先來(lái)看下這個(gè) 2 個(gè)函數(shù)的簽名:
int setjmp(jmp_buf env);void longjmp(jmp_buf env, int value);
它們都在頭文件 setjmp.h 中進(jìn)行聲明,維基百科的解釋如下:
setjmp: Sets up the local jmp_buf buffer and initializes it for the jump. This routine saves the program's calling environment in the environment buffer specified by the env argument for later use by longjmp. If the return is from a direct invocation, setjmp returns 0. If the return is from a call to longjmp, setjmp returns a nonzero value。
longjmp:Restores the context of the environment buffer env that was saved by invocation of the setjmp routine in the same invocation of the program. Invoking longjmp from a nested signal handler is undefined. The value specified by value is passed from longjmp to setjmp. After longjmp is completed, program execution continues as if the corresponding invocation of setjmp had just returned. If the value passed to longjmp is 0, setjmp will behave as if it had returned 1; otherwise, it will behave as if it had returned value。
下面我再用自己的理解把上面這段英文解釋一下:
setjmp 函數(shù)
功能:把執(zhí)行這個(gè)函數(shù)時(shí)的各種上下文信息保存起來(lái),主要就是一些寄存器的值;參數(shù):用來(lái)保存上下文信息的緩沖區(qū),相當(dāng)于把當(dāng)前的上下文信息拍一個(gè)快照保存起來(lái);返回值:有 2 種返回值,如果是直接調(diào)用 setjmp 函數(shù)時(shí),返回值是 0;如果是調(diào)用 longjmp 函數(shù)跳轉(zhuǎn)過(guò)來(lái)時(shí),返回值是非 0; 這里可以與創(chuàng)建進(jìn)程的函數(shù) fork 進(jìn)行一下類(lèi)比。
longjmp 函數(shù)
功能:跳轉(zhuǎn)到參數(shù) env 緩沖區(qū)中保存的上下文(快照)中去執(zhí)行;參數(shù):env 參數(shù)指定跳轉(zhuǎn)到哪個(gè)上下文中(快照)去執(zhí)行, value 用來(lái)給 setjmp 函數(shù)提供返回判斷信息,也就是說(shuō):調(diào)用 longjmp 函數(shù)時(shí),這個(gè)參數(shù) value 將會(huì)作為 setjmp 函數(shù)的返回值;返回值:沒(méi)有返回值。因?yàn)樵谡{(diào)用這個(gè)函數(shù)時(shí),就直接跳轉(zhuǎn)到其他地方的代碼去執(zhí)行了,不會(huì)再回來(lái)了。
小結(jié):這 2 個(gè)函數(shù)是配合使用的,用來(lái)實(shí)現(xiàn)程序的跳轉(zhuǎn)。

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
圖片新聞
-
馬云重返一線督戰(zhàn),阿里重啟創(chuàng)始人模式
-
機(jī)器人奧運(yùn)會(huì)戰(zhàn)報(bào):宇樹(shù)機(jī)器人摘下首金,天工Ultra搶走首位“百米飛人”
-
存儲(chǔ)圈掐架!江波龍起訴佰維,索賠121萬(wàn)
-
長(zhǎng)安汽車(chē)母公司突然更名:從“中國(guó)長(zhǎng)安”到“辰致科技”
-
豆包前負(fù)責(zé)人喬木出軌BP后續(xù):均被辭退
-
字節(jié)AI Lab負(fù)責(zé)人李航卸任后返聘,Seed進(jìn)入調(diào)整期
-
員工持股爆雷?廣汽埃安緊急回應(yīng)
-
中國(guó)“智造”背后的「關(guān)鍵力量」
最新活動(dòng)更多
-
10月23日火熱報(bào)名中>> 2025是德科技創(chuàng)新技術(shù)峰會(huì)
-
10月23日立即報(bào)名>> Works With 開(kāi)發(fā)者大會(huì)深圳站
-
10月24日立即參評(píng)>> 【評(píng)選】維科杯·OFweek 2025(第十屆)物聯(lián)網(wǎng)行業(yè)年度評(píng)選
-
即日-11.25立即下載>>> 費(fèi)斯托白皮書(shū)《柔性:汽車(chē)生產(chǎn)未來(lái)的關(guān)鍵》
-
11月27日立即報(bào)名>> 【工程師系列】汽車(chē)電子技術(shù)在線大會(huì)
-
12月18日立即報(bào)名>> 【線下會(huì)議】OFweek 2025(第十屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會(huì)
推薦專(zhuān)題
- 1 特斯拉工人被故障機(jī)器人打成重傷,索賠3.6億
- 2 【行業(yè)深度研究】退居幕后四年后,張一鳴終于把算法公司變成AI公司?
- 3 AI 時(shí)代,阿里云想當(dāng)“安卓” ,那誰(shuí)是“蘋(píng)果”?
- 4 華為公布昇騰芯片三年計(jì)劃,自研HBM曝光
- 5 硬剛英偉達(dá)!華為發(fā)布全球最強(qiáng)算力超節(jié)點(diǎn)和集群
- 6 機(jī)器人9月大事件|3家國(guó)產(chǎn)機(jī)器人沖刺IPO,行業(yè)交付與融資再創(chuàng)新高!
- 7 谷歌“香蕉”爆火啟示:國(guó)產(chǎn)垂類(lèi)AI的危機(jī)還是轉(zhuǎn)機(jī)?
- 8 00后華裔女生靠?jī)刹緼I電影狂賺7.8億人民幣,AI正式進(jìn)軍好萊塢
- 9 美光:AI Capex瘋投不止,終于要拉起存儲(chǔ)超級(jí)周期了?
- 10 華為已殺入!AI領(lǐng)域最熱黃金賽道,大廠的數(shù)字人美女讓我一夜沒(méi)睡著覺(jué)