C++無try-catch的異常捕獲示例詳解
try-catch
在c++中,我們可以非常方便的使用try catch來捕獲異常
try { throw 1; } catch (int x) { cout << "x " << x << endl; throw std::runtime_error("exception"); } catch (...) { cout << "exception" << endl; }
你可能有時(shí)候 c++的try-catch沒什么用
但事實(shí)上,在解決某些問題方面,c++的異常強(qiáng)過你自己打flag 判斷 比如下面這個(gè)例子
void dep2() { cout << "ok" << endl; throw "error"; } void dep1() { dep2(); cout << "ok call dep2" << endl; } void func() { dep1(); cout << "ok call dep1" << endl; } signed main() { try { func(); } catch (...) { cout << "error" << endl; } return 0; }
不使用try-catch 可以怎么寫?
pair<int, string> dep2() { cout << "ok" << endl; return {-1, "error"}; cout << "ret" << endl; return {0, ""}; } pair<int, string> dep1() { auto[ret, err] = dep2(); if (ret == -1) return {ret, err}; cout << "ok call dep2" << endl; return {0, ""}; } pair<int, string> func() { auto[ret, err] = dep1(); if (ret == -1) return {ret, err}; cout << "ok call dep1" << endl; return {0, ""}; } signed main() { auto[ret, err] = func(); if (ret == -1) cout << err << endl; return 0; }
可以看出, try-catch還是可以幫助我們減少一些沒必要的判段和代碼
沒有try-catch的日子
上述是c++的。那么。。。c語言怎么辦呢? 那么,大抵是這樣的 用返回值來充當(dāng)狀態(tài)碼返回,傳參留一個(gè)空位接受返回?cái)?shù)據(jù)。
/** * -1 error * 0 ok * other **/ int func(int parameter, int* ret) {}
goto 是什么?
goto 語句允許把控制無條件轉(zhuǎn)移到同一函數(shù)內(nèi)的被標(biāo)記的語句在任何編程語言中,都不建議使用 goto 語句。因?yàn)樗沟贸绦虻目刂屏麟y以跟蹤,使程序難以理解和難以修改。任何使用 goto 語句的程序可以改寫成不需要使用 goto 語句的寫法。E.W.Dijikstra 在1965年提出結(jié)構(gòu)化程序設(shè)計(jì)來規(guī)避這種錯(cuò)誤
goto 就沒有他的優(yōu)點(diǎn)的嗎?
goto是個(gè)好東西,就是得小心用。
現(xiàn)在的建議是不使用goto,且把goto妖魔化了
確實(shí)可以使用 while for之類的東西來替代goto
但是在有些時(shí)候,goto還是有一丟丟作用的。
例如:
signed main() { for (int i = 1; i <= 1000; i++) { for (int j = 1; j <= 1000; j++) { for (int k = 1; k <= 1000; k++) { if (i == 11 && j == 22 && k == 555) goto end; } } } end: return 0; } signed main() { bool flag = true; for (int i = 1; i <= 1000 && flag; i++) { for (int j = 1; j <= 1000 && flag; j++) { for (int k = 1; k <= 1000 && flag; k++) { if (i == 11 && j == 22 && k == 555) flag = false; } } } return 0; }
拋開程序本身不談,有時(shí)候使用goto跳出多級(jí)循環(huán)的便利性,更勝一籌。
不同函數(shù)之間跳轉(zhuǎn)
上述講的goto只能在同一個(gè)函數(shù)內(nèi)進(jìn)行跳轉(zhuǎn),不能夠跨函數(shù)跳轉(zhuǎn)
setjmp 和 longjmp
setjmp
setjmp()函數(shù)保存關(guān)于調(diào)用環(huán)境的各種信息(通常是堆棧指針、 緩沖區(qū)env中的指令指針,可能是其他寄存器的值和信號(hào)掩碼) 稍后由longjmp()使用。調(diào)用時(shí),setjmp()返回0。(用man setjmp查看更詳細(xì)的介紹)
創(chuàng)建本地的jmp_buf緩沖區(qū)并且初始化,用于將來跳轉(zhuǎn)回此處。這個(gè)子程序保存程序的調(diào)用環(huán)境于env參數(shù)所指的緩沖區(qū),env將被longjmp使用。如果是從setjmp直接調(diào)用返回,setjmp返回值為0。如果是從longjmp恢復(fù)的程序調(diào)用環(huán)境返回,setjmp返回非零值。
longjmp
在執(zhí)行l(wèi)ongjmp之時(shí),傳入一個(gè)保存好的jmp_buf和一個(gè)返回值,程序就會(huì)切換上下文跨函數(shù)的跳轉(zhuǎn)到 之前設(shè)置的setjump處執(zhí)行。
例子
jmp_buf env; signed main() { int stat = 0; if ((stat = setjmp(env)) == 1) { printf("1"); return 1; } printf("0"); longjmp(env, 1); return 0; } // 結(jié)果: >. 01
原理,進(jìn)程是一個(gè)狀態(tài)機(jī),我們當(dāng)前的執(zhí)行時(shí)刻擁有的狀態(tài)有 寄存器的值,pc指針,堆棧信息等。 和上下文切換一樣,我們可以保存一下當(dāng)前進(jìn)程的信息在jmp_buf里面,然后,等longjmp調(diào)用時(shí),再去以保存的時(shí)候的進(jìn)程信息去“切換”掉當(dāng)前的狀態(tài)信息,實(shí)現(xiàn)了跳轉(zhuǎn)執(zhí)行的過程,由于這個(gè)和上下文切換還是有區(qū)別,是切換回去當(dāng)前進(jìn)程。所以保存一下必要的寄存器值就可以了。
無try-catch的異常捕獲
利用宏替換和switch來匹配錯(cuò)誤
可以簡(jiǎn)單的實(shí)現(xiàn)異常的捕獲和跳轉(zhuǎn)
(還是c++的try-catch更強(qiáng)大)
#include <bits/stdc++.h> #include <setjmp.h> struct EXP { jmp_buf buf; int stat; }; #define BEGIN_EXP(exp) switch (setjmp(exp.buf)) #define TRY(body) case 0: body break; #define CATCH(exp, body) case exp: body break; #define THROW(exp, data) longjmp(exp.buf, data) int main() { EXP exp; BEGIN_EXP(exp) { TRY({ std::cout << " data" << std::endl; THROW(exp, 1); }) CATCH(1, { std::cout << "error 1" << std::endl; THROW(exp, 2); }) CATCH(2, { std::cout << "error 2" << std::endl; THROW(exp, 3); }) CATCH(3, { std::cout << "error 2" << std::endl; }) } return 0; }
以上就是C++無try-catch的異常捕獲示例詳解的詳細(xì)內(nèi)容,更多關(guān)于C++無try-catch異常捕獲的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++中for循環(huán)與while循環(huán)的區(qū)別總結(jié)
這篇文章主要給大家介紹了關(guān)于C++中for循環(huán)與while循環(huán)的區(qū)別的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10C++ map 根據(jù)value找key的實(shí)現(xiàn)
今天小編就為大家分享一篇C++ map 根據(jù)value找key的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-12-12C語言模擬實(shí)現(xiàn)動(dòng)態(tài)通訊錄
本文主要介紹了C語言模擬實(shí)現(xiàn)動(dòng)態(tài)通訊錄,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07