1. 程式人生 > >C++筆記 第六十三課 C語言異常處理---狄泰學院

C++筆記 第六十三課 C語言異常處理---狄泰學院

如果在閱讀過程中發現有錯誤,望評論指正,希望大家一起學習,一起進步。
學習C++編譯環境:Linux

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

1.異常處理

異常的概念
程式在執行過程中可能產生異常
異常(Exception)與Bug的區別
異常是程式執行時可預料的執行分支
Bug是程式中的錯誤,是不被預期的執行方式
異常(Exception)與Bug的對比:
異常:
執行時產生除0的情況
需要開啟的外部檔案不存在
陣列訪問時越界
Bug:
使用野指標
堆陣列使用結束後未釋放
選擇排序無法處理長度為0 的陣列

2.異常處理的方式

C語言經典處理方式:if…else…
在這裡插入圖片描述

63-1 除法操作異常處理

#include <iostream>
#include <string>
using namespace std;
double divide(double a, double b, int* valid)
{
    const double delta = 0.000000000001;
    double ret = 0;
    if( !((-delta < b) && ( b < delta)))
    {
	ret = a / b;
	*valid = 1;
    }
    else
    {
	*valid = 0 ;
    }
    return ret;
}
int main(int argc, char *argv[])
{
    int valid = 0;
    //double r = divide(1,1,&valid); // r=1
    double r = divide(1,0,&valid); //Divided by zero...
    if( valid )
    {
	cout << "r = "<<r << endl;
    }
    else
    {
	cout << "Divided by zero..." << endl;
    }
    
    return 0;
}
執行結果
r=1
Divided by zero...

缺陷:
divide函式有3個引數,難以理解其用法
divide函式呼叫後必須判斷valid代表的結果
當valid為true時,運算結果正常
當valid為false時,運算過程出現異常
通過setjmp()和longjmp()進行優化—這兩個函式會破壞結構化程式設計的特性(順序執行,分支執行,迴圈執行)
int setjmp(jmp_buf env)
將當前上下文儲存在jmp_buf結構體中
void longjmp_(jmp_buf env, int val)
從jmp_buf結構體中恢復setjmp()儲存的上下文
最終從setjmp函式呼叫點返回,返回值為val

63-2 除法操作異常處理優化–由此程式得出還不如63-1程式好理解,好用

#include <iostream>
#include <string>
#include <csetjmp>//兩個函式所在的庫
using namespace std;
static jmp_buf env;
double divide(double a, double b)
{
    const double delta = 0.000000000001;
    double ret = 0;
    if( !((-delta < b) && ( b < delta)))
    {
	ret = a / b;
    }
    else
    {
	longjmp(env, 1);
    }
    return ret;
}
int main(int argc, char *argv[])
{
    if( setjmp(env) == 0 )
    {
	double r = divide(1,1);
	cout << "r = "<< r << endl;
    }
    else
    {
	cout << "Divided by zero..." << endl;
    }
    
    return 0;
}
執行結果
r = 1

缺陷
setjmp()和longjmp()的引入
必然涉及到使用全域性變數
暴力跳轉導致程式碼可讀性降低
本質還是if…else…異常處理方式
C語言中的經典異常處理方式會使得程式中邏輯中混入大量的處理異常的程式碼。正常邏輯程式碼和異常處理程式碼混合在一起,導致程式碼迅速膨脹,難以維護。

63-3 異常處理程式碼分析

#include <iostream>
#include <string>
using namespace std;
#define SUCCESS           0 
#define INVALID_POINTER   -1
#define INVALID_LENGTH    -2
#define INVALID_PARAMETER -3
int MemSet(void* dest, unsigned int length, unsigned char v)
{
    if( dest == NULL )
    {
        return INVALID_POINTER;
    }
    
    if( length < 4 )
    {
        return INVALID_LENGTH;
    }
    
    if( (v < 0) || (v > 9) )
    {
        return INVALID_PARAMETER;
    }
    
    unsigned char* p = (unsigned char*)dest;
    
    for(int i=0; i<length; i++)
    {
        p[i] = v;
    }
    
    return SUCCESS;
}
int main(int argc, char *argv[])
{
    int ai[5];
    int ret = MemSet(ai, sizeof(ai), 0);
    
    if( ret == SUCCESS )
    {
    }
    else if( ret == INVALID_POINTER )
    {
    }
    else if( ret == INVALID_LENGTH )
    {
    }
    else if( ret == INVALID_PARAMETER )
    {
    }
    
    return ret;
}

由這個程式可以得出C語言沒有辦法進行更好的異常處理啦,等C++語言的啦。

3.問題

C++中有沒有更好的異常處理方式?有,64,65說明的
小結
程式中不可避免的會發生異常
異常是在開發階段就可以預見的執行時問題
C語言中通過經典的if…else…方式處理異常
C++中存在更好的異常處理方式