2016-08-11 60 views
0

引用分配的內存結構的正確方法,我有以下功能:釋放內存爲包含指針

/* undef: from s from hashtab */ 
void undef(char *s) { 
    struct nlist *currentPtr, *previousPtr; 

    for (previousPtr = NULL, currentPtr = hashtab[hash(s)]; 
      currentPtr != NULL; 
      previousPtr = currentPtr, currentPtr = currentPtr->next) { 

     if (strcmp(currentPtr->name, s) == 0) { 
      if (previousPtr == NULL) /* first element */ 
       hashtab[hash(s)] = currentPtr->next; 
      else /* element in the middle or at the end */ 
       previousPtr->next = currentPtr->next; 
      /* free memory */ 
      free(currentPtr->name); 
      free(currentPtr->defn); 
      //free(currentPtr); 
     } 
    } 
} 

currentPtr指向由malloc分配的內存。

currentPtr->namecurrentPtr->defn指向通過strdup複製的字符數組。

我不知道什麼是釋放列表項的內存的正確方法。

如果我使用

free(currentPtr->name); 
free(currentPtr->defn); 

然後我沒有得到任何分段錯誤,但我相信字符數組的內存被釋放,但列表結構元素本身是沒有的。

如果我使用

free(currentPtr); 

然後我也拿不出分段錯誤,但我相信我釋放列表結構元素本身,而不是字符數組的內存。

使用

free(currentPtr->name); 
free(currentPtr->defn); 
free(currentPtr); 

給我段錯誤。但我認爲這將是正確的做法。

那麼哪個是正確的?它爲什麼會失敗?

+0

FWIW,'strdup'只是'malloc'的底層。所以你不會像'malloc'那樣處理'strdup'的返回值。 –

+0

釋放'currentPtr'指針使currentPtr的值無效的內存。如果在分配給它一個新的有效值之前解引用它,那麼行爲是不確定的。即使它似乎工作。 –

回答

4

你需要改變你的策略一點點,因爲currentPtr是呼叫後懸掛指針

free(currentPtr); 

這裏是我的建議:

for (previousPtr = NULL, currentPtr = hashtab[hash(s)]; 
     currentPtr != NULL; 
     previousPtr = currentPtr) { 

    if (strcmp(currentPtr->name, s) == 0) 
    { 
     if (previousPtr == NULL) /* first element */ 
      hashtab[hash(s)] = currentPtr->next; 
     else /* element in the middle or at the end */ 
      previousPtr->next = currentPtr->next; 

     /* free memory */ 
     free(currentPtr->name); 
     free(currentPtr->defn); 

     // Get hold of the next pointer before free'ing currentPtr 
     struct nlist *tempPtr = currentPtr->next; 
     free(currentPtr); 
     currentPtr = tempPtr; 
    } 
    else 
    { 
     currentPtr = currentPtr->next; 
    } 
} 

更新,更精簡版

由於您使用currentPtr->next在四個地方,您可以簡化廁所p使用:

struct nlist *nextPtr = NULL; 
for (previousPtr = NULL, currentPtr = hashtab[hash(s)]; 
     currentPtr != NULL; 
     previousPtr = currentPtr, currentPtr = nextPtr) { 

    nextPtr = currentPtr->next; 
    if (strcmp(currentPtr->name, s) == 0) 
    { 
     if (previousPtr == NULL) /* first element */ 
      hashtab[hash(s)] = nextPtr; 
     else /* element in the middle or at the end */ 
      previousPtr->next = nextPtr; 

     /* free memory */ 
     free(currentPtr->name); 
     free(currentPtr->defn); 
     free(currentPtr); 
    } 
}