基本避免Memory Leak的技巧 @ H's 筆記本 :: 隨意窩 Xuite日誌
  • 關鍵字
    1. 沒有新回應!
  • 2006-02-25 15:40 基本避免Memory Leak的技巧
    平均分數:0 顆星    投票人數:0
    我要評分:

    基本避免Memory Leak的技巧 — garylee

    很多程式初學者比較沒有在注意一些Memory處理上的問題。其實只要平時稍微注意一下,就可以避免掉很多問題,而且也可以讓你的程式更好以及更穩定。

    首先,是指標變數內容的問題。通常各位在使用指標時,可能習慣不給予初始值。其實這會造成一些問題。所以建議大家宣告指標變數時一律給予初值。若無法在宣告的同時一併配置記憶體,那麼請給予NULL作為初值。例如:

    TList *myList = NULL ;

    另外,許多在delete後,大家可能也就不再理會該指標的內容了。其實,這也是會造成一些麻煩。因為記憶體被delete可能只是系統作一個記號在記憶配置表中,表示該記憶體是free的。原來的記憶體內還是有原先的內容。但是你的程式一個不注意,又去把原來的指標拿起來用。如果馬上就出錯的話,這樣還好。偏偏因為原來的內容都還在,所以這個錯誤會延遲產生影響。這種類型的Bug特別難抓!因為,你根本找不到引發問題的所在,如果你有個地方一直發生Access Violation,可是該地方的程式碼你已經check過十幾次了,還是找不問題,那很可能你就是遇到這樣的問題。以前在寫一些程式時,我就曾經為了這樣的Bug,弄了三天。可見其傷害有多大。

    所以,當delete某指標後,其務必將其內容設為NULL。一方面是使用NULL指標,一定是馬上出錯。所以你的Bug一下就會抓到。另外一個
    理由是如果你不小心重複delete同一個物件時,一樣會發生延遲影響的錯誤。但是delete一個NULL指標,在BCB內是什麼也不做。所以不
    用擔心會發生問題。

    總結以上提供下面幾個比較方便MACRO給大家使用:


    SAFENEW
    SAFEDELETE
    SAFEDELETE_ARRAY

    其中,SAFENEW是用來配置記憶體使用。與一般new不同的是,當配置記憶體產生Exception或是配置不出記憶體時,會產生一個訊息視窗警告。並且,將該指標內容設定為 NULL。

    而SAFEDELETE再delete前會先檢查該指標是否為NULL。若是就進行delete動作,並且在delete完後將該指標內容設定為NULL。SAFEDELETE_ARRAY也是一樣的作用,只是他是用來刪除陣列指標用的。例如:

    TList *myList = NULL ;
    char *string = NULL ;

    上面這三個Macro你可在本文最後的程式列表找到。

    SAFENEW(myList, TList());
    SAFENEW(string, char[10]);
    ...

    SAFEDELETE(myList);
    SAFEDELETE(string);

    如果你的配置的物件只是暫時性的,也就是說只用在某個function之內。強烈建議你使用auto_ptr。因為,使用了auto_ptr你就無須擔心記憶體是否被釋放掉。只要離開該function或是某個scope,記憶體肯定會被釋放。你就不用老是想著要在哪裡釋放記憶體。不用在每個return前面寫上一堆delete動作。如果你的程式是使用goto的方式或者寫的像下面這樣…..拜託改用auto_ptr吧…


    TList *myList = new TList() ;
    TButton *btn = new TButton(this);
    char *ptr = new char ;

    ...
    if(OpenFileFailed)
    {
    delete myList ;
    delete btn ;
    delete ptr ;
    return ;
    }

    ...
    if(OtherFailure)
    {
    delete myList ;
    delete btn ;
    delete ptr ;
    return ;
    }

    ...
    if(SomeThingTrue)
    {
    delete myList ;
    delete btn ;
    delete ptr ;
    return ;
    }

    delete myList ;
    delete btn ;
    delete ptr ;
    return ;

    如果你的程式配置了記憶體可是你也沒有用goto的方式,也沒有寫成向上面那樣,也沒有使用auto_ptr,也沒有用其它技術來釋放記憶體….

    那麼……你該死了……Memory Leak最多的一定就是你…

    safepointer.h 列表:

    /**
    * @file SAFE pointer access include file.
    * @author Gary W. Lee
    */

    #ifndef __SAFEPOINTER_H__
    #define __SAFEPOINTER_H__

    #ifdef WINDOWS
    #define SP_SHOWMSG(msg) MessageBox(NULL, (msg), ,"ERROR", MB_OK)
    #else
    #define SP_SHOWMSG(msg) fprintf(stderr, "%s\n", (msg))
    #endif

    #define SAFENEW(p,t) try { \
    if(((p) = new t)==NULL) \
    { \
    SP_SHOWMSG("Virtual memory exhausted! Program Exit!"); \
    } \
    } catch (Exception &e) { \
    SP_SHOWMSG(e.Message.c_str()); \
    p = NULL ; \
    }/// 讓物件記憶體配置後檢查是否配置成功。

    #define SAFEDELETE(p) if((p)) \
    { delete (p); p = NULL; } /// 讓物件被delete後,將其值設為NULL。並且在delet物件之前,先確定該指標不為NULL。

    #define SAFEDELETE_ARRAY(p) if((p)) \
    { delete [] (p); p = NULL; } /// 讓物件Array被delete後,將其值設為NULL。並且在delet物件之前,先確定該指標不為NULL。

    #endif // end of !__SAFEPOINTER_H__

    H / Xuite日誌 / 回應(1) / 引用(0) / 好文轉寄
    回應