簡體   English   中英

為包含指針引用的已分配內存的結構釋放內存的正確方法

[英]Correct way to free memory for a structure that contains allocated memory referenced by pointers

我有以下功能:

/* 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分配的malloc

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

我不確定釋放列表項的內存的正確方法是什么。

如果我用

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

那么我不會遇到任何分段錯誤,但是我相信字符數組內存已釋放,但列表結構元素本身並未釋放。

如果我用

free(currentPtr);

那么我也不會遇到任何分段錯誤,但是我相信我釋放了列表結構元素本身,但沒有釋放字符數組內存。

運用

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

給我分段錯誤。 但是我認為這將是正確的方法。

那么哪個正確呢? 為什么會失敗?

您需要稍微更改策略,因為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 ,因此可以使用以下方法簡化循環:

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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM