如何利用C語言中的setjmp和longjmp實現(xiàn)異常捕獲和協(xié)程?
這是道哥的第 017 篇原創(chuàng)
一、前言
二、函數(shù)語法介紹
與 goto 語句比較
與 fork 函數(shù)比較
與 Python 語言中的 yield/resume 比較
三、利用 setjmp/longjmp 實現(xiàn)異常捕獲
四、利用 setjmp/longjmp 實現(xiàn)協(xié)程
五、總結(jié)
一、前言
在 C 標(biāo)準(zhǔn)庫中,有兩個威力很猛的函數(shù):setjmp 和 longjmp,不知道各位小伙伴在代碼中是否使用過?我問了身體的幾位同事,一部分人不認(rèn)識這兩個函數(shù),有一部分人知道這個函數(shù),但從來沒有使用過。
從知識點范圍來看,這兩個函數(shù)的功能比較單純,一個簡單的示例代碼就能說清楚了。但是,我們需要從這個知識點進(jìn)行發(fā)散、思考,在不同的維度上,把這個知識點與這個編程語言中其它類似的知識進(jìn)行聯(lián)想、對比;與其他編程語言中類似的概念進(jìn)行比較;然后再思考這個知識點可以使用在哪些場合,別人是怎么來使用它的。
今天,我們就來掰扯掰扯這兩個函數(shù)。雖然在一般的程序中使用不上,但是在今后的某個場合,當(dāng)你需要處理一些比較奇特的程序流程時,也許它們可以給你帶來意想不到的效果。
例如:我們會把 setjmp/longjmp 與 goto 語句進(jìn)行功能上的比較;與 fork 函數(shù)從返回值上進(jìn)行類比;與 Python/Lua 語言中的協(xié)程進(jìn)行使用場景上的比較。
二、函數(shù)語法介紹
1. 最簡示例
先不講道理,直接看一下這個最簡單的示例代碼,看不懂也沒關(guān)系,混個臉熟:
int main(){ // 一個緩沖區(qū),用來暫存環(huán)境變量 jmp_buf buf; printf("line1 "); // 保存此刻的上下文信息 int ret = setjmp(buf); printf("ret = %d ", ret); // 檢查返回值類型 if (0 == ret) { // 返回值0:說明是正常的函數(shù)調(diào)用返回 printf("line2 "); // 主動跳轉(zhuǎn)到 setjmp 那條語句處 longjmp(buf, 1); } else { // 返回值非0:說明是從遠(yuǎn)程跳轉(zhuǎn)過來的 printf("line3 "); } printf("line4 "); return 0;}
執(zhí)行結(jié)果:
執(zhí)行順序如下(如果不明白就不要深究,看完下面的解釋再回過頭來看):
2. 函數(shù)說明
首先來看下這個 2 個函數(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í)行這個函數(shù)時的各種上下文信息保存起來,主要就是一些寄存器的值;參數(shù):用來保存上下文信息的緩沖區(qū),相當(dāng)于把當(dāng)前的上下文信息拍一個快照保存起來;返回值:有 2 種返回值,如果是直接調(diào)用 setjmp 函數(shù)時,返回值是 0;如果是調(diào)用 longjmp 函數(shù)跳轉(zhuǎn)過來時,返回值是非 0; 這里可以與創(chuàng)建進(jìn)程的函數(shù) fork 進(jìn)行一下類比。
longjmp 函數(shù)
功能:跳轉(zhuǎn)到參數(shù) env 緩沖區(qū)中保存的上下文(快照)中去執(zhí)行;參數(shù):env 參數(shù)指定跳轉(zhuǎn)到哪個上下文中(快照)去執(zhí)行, value 用來給 setjmp 函數(shù)提供返回判斷信息,也就是說:調(diào)用 longjmp 函數(shù)時,這個參數(shù) value 將會作為 setjmp 函數(shù)的返回值;返回值:沒有返回值。因為在調(diào)用這個函數(shù)時,就直接跳轉(zhuǎn)到其他地方的代碼去執(zhí)行了,不會再回來了。
小結(jié):這 2 個函數(shù)是配合使用的,用來實現(xiàn)程序的跳轉(zhuǎn)。

請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個字
最新活動更多
-
即日-9.1立即下載>> 【限時下載】ADI中國三十周年感恩回饋助力企業(yè)升級!
-
即日-9.14點擊進(jìn)入 >> 【限時福利】TE 2025國際物聯(lián)網(wǎng)展·深圳站
-
10月23日立即報名>> Works With 開發(fā)者大會深圳站
-
11月27日立即報名>> 【工程師系列】汽車電子技術(shù)在線大會
-
精彩回顧立即查看>> 【在線研討會】解析安森美(onsemi)高精度與超低功耗CGM系統(tǒng)解決方案
-
精彩回顧立即查看>> 【在線會議】CAE優(yōu)化設(shè)計:醫(yī)療器械設(shè)計的應(yīng)用案例與方案解析
推薦專題
- 1 傳魏建軍與賈躍亭合作,長城汽車出海美國
- 2 黃仁勛:與雷軍長期合作,共探AI智駕
- 3 阿里首位程序員,“掃地僧”多隆已離職
- 4 先進(jìn)算力新選擇 | 2025華為算力場景發(fā)布會暨北京xPN伙伴大會成功舉辦
- 5 2025年第一支10倍股,來了!
- 6 清華跑出具身智能獨角獸:給機(jī)器人安上眼睛和大腦,融資近20億
- 7 特朗普要求英特爾首位華人 CEO 辭職
- 8 騰訊 Q2 財報亮眼:AI 已成第二增長曲線
- 9 具身智能機(jī)器人量產(chǎn)前夜,標(biāo)準(zhǔn)機(jī)腦正在成型
- 10 共探合作新機(jī)遇!江門市新會區(qū)(深圳)“AI + 機(jī)器人” 產(chǎn)業(yè)對接會成功舉辦