2013-06-11 253 views
3

在對待一個庫,在所提供的示例源代碼鑄造double類型的變量char類型的變量,我發現下面的代碼:ç釋放內存

x  = (double *) malloc (narcs * sizeof (double)); 
dj = (double *) malloc (narcs * sizeof (double)); 
pi = (double *) malloc (nnodes * sizeof (double)); 
slack = (double *) malloc (nnodes * sizeof (double)); 

我發現沒有什麼特別的在這裏,但釋放內存時,源代碼示例執行以下操作:

free_and_null ((char **) &x); 
free_and_null ((char **) &dj); 
free_and_null ((char **) &pi); 
free_and_null ((char **) &slack); 

的free_and_null代碼是:

static void 
free_and_null (char **ptr) 
{ 
    if (*ptr != NULL) { 
    free (*ptr); 
    *ptr = NULL; 
    }; 
}; 

我的問題是爲什麼,釋放以前分配的內存時,它完成鑄造爲char雙指針。我的問題是,爲什麼這樣做是這樣,使用自定義函數來釋放內存,以及爲什麼它被選爲一個char **這個函數的參數。

我知道,肯定是這個問題是因爲我仍然有限的C語言知識的發生,但無論如何,任何人都可以解釋爲什麼這樣做,如果這是一個很好的做法。

+0

您不需要在C程序中投射'malloc'的返回值。 –

+0

假設所有指針具有相同的大小和表示形式,是否構建char *'或'void *','free_and_null'。這是馬虎。我不會使用它。 –

+0

是不是'*(char **)(&x)= NULL'未定義的行爲? (當x是'double *') – asaelr

回答

9

我同意你的看法 - 即代碼是有點怪。沒有理由筆者不可能很容易地使用void **

此外,if (*ptr != NULL)檢查是不必要的,因爲free(NULL)是完全合法的。大括號後的;字符也不是必需的。

一個簡單的版本可能是這樣的:

static void free_and_null(void **ptr) 
{ 
    free(*ptr); 
    *ptr = NULL; 
} 

該功能存在於所有的原因是爲了確保釋放指針設置爲NULL,是用於檢測釋放後使用無漏洞和樂於助人完全避免雙重錯誤。

編輯:星際飛行員下方暗示,它可能是一個好主意,檢查ptr本身不是NULL:

static void free_and_null(void **ptr) 
{ 
    if (ptr) 
    { 
     free(*ptr); 
     *ptr = NULL; 
    } 
} 
+1

我懷疑很多C代碼仍受C早期版本的嚴重影響,尤其是K&R定義時的「早期」。所以,儘管現在已經定義了「free(NULL)」,但這肯定不是20年前的保證行爲。當我第一次學習C時,使用「無效」構造也不那麼流行,回到了朦朧和遙遠的過去。或者,也許我的記憶已經消退。 –

+0

我同意,除了這個函數的返回類型是'void',所以指向其他事情正在進行。當'free(NULL)'行爲被標準化時,我不確定。 –

+0

實際上,代碼應該檢查'ptr'不是'NULL',而不是'* ptr'。如果一個'NULL'指針被傳入,然後代碼嘗試解引用它,可能會發生樂趣。 – StarPilot

2

原因間接的額外級別(**)是因爲這讓筆者free_and_null將指針設置爲NULL。如果他們只是傳遞*或x,他們就會得到一個按值傳遞的指針副本。

static void 
free_and_null (char *ptr) 
{ 
    if (ptr != NULL) { 
    free (ptr); 
// *ptr = NULL; CAN'T DO THIS NOW 
    }; 
}; 

這不是一個壞主意後,分配的內存已經被釋放,因爲它可以幫助檢測內存泄漏的指針重置爲NULL。我不會嚴格按照以上作者的風格,但我認爲這可以幫助你理解基本原理。正如卡爾指出的void **本來是一個更合適的簽名。您經常會看到C代碼,其中人們使用char*作爲「通用」類型的指針類型 - 這是錯誤的,在此上下文中沒有足夠的理由使用char。

0

另一種方法,避免了指針的指針,將僅僅是:

void *free_and_null_back(void *p) { 
    free(p); 
    return NULL; 
    } 

用法:

p = free_and_null(p); 

或者,#define球迷:

#define free(p) free(p);(p)=null; 

顯然隨所有關於#定義危險的常見警告...