異常處理,保證代碼穩定的必經之步—-小話c語言(12)

來源:互聯網
上載者:User

[Mac 10.7.1 Lion  Intel-based  x64  gcc4.2.1]

Q: c語言的異常處理可以使用什嗎?

A: 可以使用setjmp和longjmp的組合。一個是儲存處理異常前執行的環境,一個是調回原來執行的環境。

int  setjmp(jmp_buf env);

參數env的類型jmp_buf定義如下:

/* * _JBLEN is number of ints required to save the following: * eax, ebx, ecx, edx, edi, esi, ebp, esp, ss, eflags, eip, * cs, de, es, fs, gs == 16 ints * onstack, mask = 2 ints */#define _JBLEN (18)typedef int jmp_buf[_JBLEN];

可以看到jmp_buf是個數群組類型,含有18個int類型資料,包括eax, ebp, esp, eip等環境變數。

它會返回0,便於外部判斷進入異常處理邏輯。

void  longjmp(jmp_buf env, int val);

第一個參數為setjmp設定的jmp_buf, 第二個參數為返回異常處理的異常參數,可自訂。

下面是個簡單的例子:

#include <stdio.h>#include <string.h>#include <setjmp.h>#define PRINT_D(intValue)     printf(#intValue" is %d\n", (intValue));#define PRINT_STR(str)      printf(#str" is %s\n", (str));jmp_buf buf;// exception processvoid exception_process(){    printf("exception process begin...\n");    longjmp(buf, 1);        // return to the normal process    printf("never execute this...\n");  // so, this line can't be executed}int main(){    int ret;    printf("main begin...\n");    ret = setjmp(buf);  // save current execute enviroment, go to exception process    if(ret)    {        // returned by exception process        printf("pass exception process ...\n");        printf("main end ...\n");    }    else    {        exception_process();    }        return 0;}

可以看到setjmp和longjmp因為共同操作了jmp_buf buf;全域變數,所以它們可以在不同函數跳轉並正確返回執行。main函數開始setjmp(buf)一定會返回0, 所以進入exception_process常式,進入後,longjmp(buf, 1);會返回之前執行的地方,進入main的if(ret)邏輯中,執行異常發生後的代碼。

執行結果:

Q: 上面代碼中的buf全域變數可以採用局部變數嗎?

A: 是的,但是需要將buf傳遞給異常處理部分。如下代碼:

#include <stdio.h>#include <string.h>#include <setjmp.h>#define PRINT_D(intValue)     printf(#intValue" is %d\n", (intValue));#define PRINT_STR(str)      printf(#str" is %s\n", (str));// exception processvoid exception_process(jmp_buf buf){    printf("exception process begin...\n");    longjmp(buf, 1);        // return to the normal process    printf("never execute this...\n");  // so, this line can't be executed}int main(){    jmp_buf buf;    int ret;    printf("main begin...\n");    ret = setjmp(buf);  // save current execute enviroment, go to exception process    if(ret)    {        // returned by exception process        printf("pass exception process ...\n");        printf("main end ...\n");    }    else    {        exception_process(buf);    }        return 0;}

可以看到exception_process多了一個參數,用於buf的傳遞。

運行結果:

Q: 如果異常原因有幾種,怎麼分辨處理?

A: 這個就需要用到longjmp第二個參數了。

#include <stdio.h>#include <string.h>#include <setjmp.h>#define PRINT_D(intValue)     printf(#intValue" is %d\n", (intValue));#define PRINT_STR(str)      printf(#str" is %s\n", (str));// input error processvoid exception_input_error_process(jmp_buf buf){    printf("exception input error process begin...\n");    longjmp(buf, 1001);        // return to the normal process, 1001 means exception error number}// input too big processvoid exception_input_too_big_process(jmp_buf buf){    printf("exception input too big process begin...\n");    longjmp(buf, 1002);        // return to the normal process, 1002 means exception error number}int main(){    jmp_buf buf;    int ret, scanf_ret;    int n;    printf("main begin...\n");        // input n    printf("input n:");    scanf_ret = scanf("%d", &n);        ret = setjmp(buf);  // save current execute enviroment, go to exception process    if(ret)    {        // returned by exception process        printf("pass exception process ...\n");        if(ret == 1001)        {            printf("exception 1001 process end...\n");        }        else if(ret == 1002)        {            printf("exception 1002 process end...\n");        }                printf("main end ...\n");    }    else    {        if(scanf_ret < 1)            exception_input_error_process(buf);        else if(n > 100)            exception_input_too_big_process(buf);    }        return 0;}

如上,如果輸入整形格式不正確,那麼進入輸入錯誤處理;如果輸入的整形超過100,那麼進入輸入過大的處理。

運行結果:

輸入錯誤資料a:

輸入資料為101:

輸入資料50:

此時沒有發生異常。

xichen

2012-5-18 15:18:16

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.