第六十三課、C語言的異常處理


一、異常處理

1、異常的概念

(1)、程序在運行過程中可能產生異常

(2)、異常(Exception)和Bug的區別

A、異常是程序運行時可預料的執行分支

B、Bug是程序中的錯誤,是不被預期的運行方式

2、異常(Exception)和Bug的對比

(1)異常

A、運行時產生除0的情況

B、需要打開的外部文件存在

C、數組訪問越界

(2)、Bug

A、使用野指針

B、堆數組使用結束后未釋放

C、選擇排序無法處理長度為0的數組

3、C語言經典處理方式:if....else.....

#include <iostream>

using namespace std; double divide(double a, double b, int* valid) { const double delta = 0.000000000000001; double ret = 0; if(!((-delta < b) && (b < delta))) { ret = a / b; *valid = 1;  //正常
 } else { *valid = 0;    //除0錯誤
 } return ret; } int main() { int valid = 0; double r = divide(1, 0, &valid); //當第3個參數為NULL時,還是會出問題
    
    if(valid) { cout << "r = " << r << endl; } else { cout << "Divide by zero..." << endl; } return 0; }

 

 4、缺陷

(1)、divide函數有三個參數,難以理解其用法

(2)、divide函數調用后必須判斷valid代表的結果

A、當valid為true時,運算結果正常

B、valid為false時,運行結果出現異常

二、優化方式

1、通過setjmp()和longjmp()進行優化

(1)、int  setjmp(jmp_buf env)

A、將當前上下文保存在jmp_buf結構體中

(2)void setjmp(jmp_buf env, int val)

A、從jmp_buf結構體中恢復setjmp()保存上下文

B、最終從setjmp()函數調用點返回,返回值為val

#include <iostream> #include <csetjmp>  //for setjmp、longjmp();

using namespace std; static jmp_buf env;  //須定義全局的上下文環境

double divide(double a, double b) { const double delta = 0.000000000000001; double ret = 0; if(!((-delta < b) && (b < delta))) { ret = a / b; } else { longjmp(env, 1); //當錯誤發生時會跳轉到setjmp那么的代碼 //處,重新執行setjmp並把其的返回值設為1
 } return ret; } int main() { if(setjmp(env) == 0) //先保存上下文環境,剛調用時返回值為0
 { double r = divide(1, 0); cout << "r = " << r << endl; } else { cout << "Divide by zero..." << endl; } return 0; }

 

2、缺陷:setjmp()和longjmp()的引入

(1)、必須涉及到使用全局變量

(2)、暴力跳轉導致代碼可讀性降低

(3)、本質還是if...else...的處理方式

三、小結

(1)、程序中不可避免的會發生異常

(2)、異常是在開發階段就可以預見的運行時問題

(3)、C語言中通過經典的if-else

(4)、C++中存在更好的異常處理方式

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM