程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 重構C資源釋放代碼

重構C資源釋放代碼

編輯:關於C語言

今天我在維護一個C項目的時候發現有的函數內部有很多的return語句,每個return前面都有一段相同的資源釋放的代碼。代碼看起來就像這樣:

int f() {
    char *p1 = (char*)malloc(1024 * sizeof(char));


    int *p2 = (int*)malloc(10 * sizeof(int));


    ...

    if (...) {

        free(p1);


        free(p2);


        return 1;


    }

    for (...) {


        if (...) {

            free(p1);


            free(p2);


            return 2; 

        }


    }


    ...


    free(p1);

    free(p2);


    return 0;


}

 

上面的代碼資源釋放部分重復度太高,讀起來不夠清爽。更重要的是如果某一個return之前忘記了釋放資源就會發生內存洩露,只能靠程序的作者和維護者隨時提高警惕。這類問題在C++中可以通過RAII來很好地解決,但可惜C語言沒有自動析構機制,所以,我們需要通過一些技巧來達到類似的效果。看下面的代碼:
 

int void f() {

    int return_code = 0;


    char *p1 = (char*)malloc(1024 * sizeof(char));


    int *p2 = (int*)malloc(10 * sizeof(int));


    ...

    if (...) {

        return_code = 1;


        goto _END_F;

    }

    for (...) {


        if (...) {

            return_code = 2;
            goto _END_F;


        }

    }


    ...


_END_F:


    free(p1);

    free(p2);


    return return_code;


}

 

我們把資源釋放代碼統一放在函數末尾,並打上_END_F標簽,把原來return的地方用goto _END_F替換。我們通過這種方式消除了資源釋放部分的冗余代碼,也一定程度上減小了忘記釋放資源的風險。不過,由於現在需要每次在goto前面加上return_code=x,還是有一定的冗余和遺忘的危險。於是,我們可以通過下面的宏可以進一步完善:

#define RETURN(label, returnCode) { return_code = returnCode; goto label;}


這樣我們就可以用RETURN(_END_F, 2)來一並實現設置返回值和goto的效果了,即簡化了代碼,又防止忘記設置返回值。 最終重構效果如下:


 

#define RETURN(label, returnCode) { return_code = returnCode; goto label;}

int void f() {

    int return_code = 0;


    char *p1 = (char*)malloc(1024 * sizeof(char));


    int *p2 = (int*)malloc(10 * sizeof(int));


    ...

    if (...) {

        RETURN(_END_F, 1);


    }

    for (...) {


        if (...) {


            RETURN(_END_F, 2);

        }

    }


    ...


_END_F:


    free(p1);

    free(p2);


    return return_code;


}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved