C語言中文網 目錄
首頁 > 編程筆記 > C語言筆記 > 指針 閱讀:9,036

malloc和free函數使用注意事項,C語言malloc和free使用詳解

在 C 語言中,程序中 malloc 等內存分配函數的使用次數一定要和 free 相等,并一一配對使用。絕對要避免“malloc 兩次 free 一次”或者“malloc 一次 free 兩次”等情況。這就像我們的婚姻制度,必須是“一夫一妻制”,不能夠“多夫一妻”或者“一夫多妻”,這些都是不合法的,如下面的示例代碼所示:
#define MAX_BUF_SIZE 100
int main(void)
{
    /*內存釋放標志*/
    int flag = 0;
    char * p = (char *)malloc(MAX_BUF_SIZE);
    if (p == NULL)
    {
        /*...*/
    }
    if (flag == 0)
    {
        free(p);
    }
    free(p);
    return 0;
}
在上面示例代碼中,當條件“if(flag==0)”成立時,“free(p)”將被執行兩次,從而導致內存的雙重釋放錯誤。因此,應該消除這種雙重釋放潛在的風險,保證動態內存只被釋放一次,如下面的示例代碼所示:
#define MAX_BUF_SIZE 100
int main(void)
{
    /*內存釋放標志*/
    int flag = 0;
    char * p = (char *)malloc(MAX_BUF_SIZE);
    if (p == NULL)
    {
        /*...*/
    }
    if (flag == 0)
    {
        /*...*/
    }
    free(p);
    p=NULL;
    return 0;
}
當然,也可以采用下面的方式:
#define MAX_BUF_SIZE 100
int main(void)
{
    /*內存釋放標志*/
    int flag = 0;
    char * p = (char *)malloc(MAX_BUF_SIZE);
    if (p == NULL)
    {
        /*...*/
    }
    if (flag == 0)
    {
        free(p);
        p = NULL;
    }
    if (p != NULL)
    {
        free(p);
        p = NULL;
    }
    return 0;
}
除此之外,對于內存釋放還必須保證只釋放動態分配的內存,即不能用 free 來釋放非 malloc、realloc、calloc 與 aligned_alloc 等內存分配函數分配的內存空間。與此同時,也不要將指針變量進行自增或者自減操作,使其指向動態分配的內存空間中間的某個位置,然后直接釋放,這樣也有可能引起未知的錯誤。

在 free 之后必須為指針賦一個新值

在使用指針進行動態內存分配操作時,在指針 p 被 free 釋放之后,指針變量本身并沒有被刪除。如果這時候沒有將指針 p 置為 NULL,會讓人誤以為 p 是個合法的指針而在以后的程序中錯誤使用它。

如下面的示例代碼所示:
#define MAX_BUF_SIZE 100
int main(void)
{
    char * p = NULL;
    p=(char *)malloc(MAX_BUF_SIZE);
    if (p == NULL)
    {
        /*...*/
    }
    /*內存初始化*/
    memset(p, '\0', MAX_BUF_SIZE);
    strcpy(p, "hello");
    /*釋放內存*/
    if (p != NULL)
    {
        free(p);
    }
    if (p != NULL)
    {
        /*發生錯誤*/
        strcpy(p, "world");
    }
    return 0;
}
在上面的示例代碼中,第一個判斷語句:
/*釋放內存*/
if (p != NULL)
{
    free(p);
}
雖然釋放了指針變量 p,但這個時候指針變量 p 本身并沒有被刪除,其保存的地址并沒有改變。但是,此時 p 雖不是 NULL 指針,但它卻不指向合法的內存塊,成為“野指針”或稱為“懸垂指針”。接下來,在執行第二個判斷語句時:
if (p != NULL)
{
    /*發生錯誤*/
    strcpy(p, "world");
}
條件“if (p != NULL)”成立,“strcpy(p, "world");}”語句將被繼續執行,導致程序出錯。或許有人會問,“free(p)”到底釋放了什么?

“free(p)”釋放的是指針變量 p 所指向的內存,而不是指針變量 p 本身。指針變量 p 并沒有被釋放,仍然指向原來的存儲空間。

其實,指針只是一個變量,只有程序結束時才被銷毀。釋放內存空間后,原來指向這塊空間的指針還是存在的,只不過現在指針指向的這塊內存是不合法的。因此,在釋放內存后,必須把指針指向 NULL,以防止指針在后面不小心又被解引用了。

如下面的示例代碼所示:
#define MAX_BUF_SIZE 100
int main(void)
{
    char * p = NULL;
    /*內存申請*/
    p = (char *)malloc(MAX_BUF_SIZE);
    if (p == NULL)
    {
        /*...*/
    }
    /*內存初始化*/
    memset(p, '\0', MAX_BUF_SIZE);
    strcpy(p, "hello");
    /*釋放內存*/
    if (p != NULL)
    {
        free(p);
        /*在free之后給指針存儲一個新值*/
        p = NULL;
    }
    if (p != NULL)
    {
        /*發生錯誤*/
        strcpy(p, "world");
    }
    return 0;
}
現在,通過語句“p=NULL”給指針變量 p 賦予一個 NULL 值之后,第二個條件語句“if(p!=NULL)”將不成立,語句“strcpy(p,"world")”也將不會被執行。所以一定要記住一條:free(p) 完之后,一定要將指針變量 p 置為 NULL。

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo