【C语言基础】C语言异常捕获机制 - setjmp
C語言異常捕獲機制 - setjmp
快速入門
想快速入門該模塊請訪問:介紹,數據接口,示例代碼
介紹
C語言沒有C++或Java的異常捕獲機制,但可以通過setjmp/longjmp實現類似的效果:
- 使用setjmp保存當前執行環境到jmp_buf,然后默認返回0。
- 程序繼續執行,到某個地方調用longjmp,傳入上面保存的jmp_buf,以及另一個整形值(我們稱他為異常碼)。
- 此時執行點又回到調用setjmp的返回處,且返回值變成longjmp設置的值
- 可以實現跨函數跳轉
注意:
-
使用gcc或者clang優化編譯的時候,可能導致結果不符合預期。可以參考某大神的示例代碼。因此不推薦時候,異常捕獲最好還是直接使用返回值形式進行調用。https://gist.github.com/nnkken/8aea1eaf1e43a963a9309c98ae4f891e
-
此外,setjmp只能設置最近一次執行環境,而且longjmp也只能是回到上一次設置setjmp中,因此并不支持設置多個執行環境
數據與接口
頭文件
- ?#include <setjmp.h>
數據
- ?環境堆棧類型 : jmp_buf
接口
-
?設置環境堆棧 int setjmp( jmp_buf env );
-
?跳轉至環境堆棧并返回指定值 void longjmp( jmp_buf env, int value );
接口介紹
setjmp
? setjmp函數用于保存程序的運行時的堆棧環境,接下來的其它地方,你可以通過調用longjmp函數來恢復先前被保存的程序堆棧環境。當 setjmp和longjmp組合一起使用時,它們能提供一種在程序中實現“非本地局部跳轉”(“non-local goto”)的機制。并且這種機制常常被用于來實現,把程序的控制流傳遞到錯誤處理模塊之中;或者程序中不采用正常的返回(return)語句,或函數的正常調用等方法,而使程序能被恢復到先前的一個調用例程(也即函數)中。
對setjmp函數的調用時,會保存程序當前的堆棧環境到env參數中;接下來調用longjmp時,會根據這個曾經保存的變量來恢復先前的環境,并且當前的程序控制流,會因此而返回到先前調用setjmp時的程序執行點。此時,在接下來的控制流的例程中,所能訪問的所有的變量(除寄存器類型的變量以外),包含了longjmp函數調用時,所擁有的變量。
longjmp
? longjmp函數用于恢復先前程序中調用的setjmp函數時所保存的堆棧環境。setjmp和longjmp組合一起使用時,它們能提供一種在程序中實現“非本地局部跳轉”(“non-local goto”)的機制。并且這種機制常常被用于來實現,把程序的控制流傳遞到錯誤處理模塊,或者不采用正常的返回(return)語句,或函數的正常調用等方法,使程序能被恢復到先前的一個調用例程(也即函數)中。
對setjmp函數的調用時,會保存程序當前的堆棧環境到env參數中;接下來調用longjmp時,會根據這個曾經保存的變量來恢復先前的環境,并且因此當前的程序控制流,會返回到先前調用setjmp時的執行點。此時,value參數值會被setjmp函數所返回,程序繼續得以執行。并且,在接下來的控制流的例程中,它所能夠訪問到的所有的變量(除寄存器類型的變量以外),包含了longjmp函數調用時,所擁有的變量;而寄存器類型的變量將不可預料。setjmp函數返回的值必須是非零值,如果longjmp傳送的value參數值為0,那么實際上被setjmp返回的值是1。
偽代碼
res = setjmp(env); if (res == 0) {try dosomething...(contain longjmp) } else {exception dosomething... }示例:比大小
#include <stdio.h> #include <setjmp.h>#define CORRECT_NUM 5 jmp_buf g_env;void err_1(void) {printf("raise err 1: num is small\n");longjmp(g_env, 1); }void err_2(void) {printf("raise err 2: num is large\n");longjmp(g_env, 2); }void work_func(int num) {if (num == CORRECT_NUM) {printf("num is correct\n");} else if (num < CORRECT_NUM) {err_1();} else {err_2();} }int main() {int num;scanf("%d", &num);int res = setjmp(g_env);if (res == 0) {/* try */work_func(num);} else {/* exception */printf("res = %d\n", res);}return 0; }參考鏈接
總結
以上是生活随笔為你收集整理的【C语言基础】C语言异常捕获机制 - setjmp的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: createdroptargets_使用
- 下一篇: 2021中卫一中高考成绩查询,2021年