为包含指针引用的已分配内存的结构释放内存的正确方法

标签 c free

我有以下功能:

/* 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);

给我段错误。但我认为这是正确的做法。

那么哪个是正确的呢?为什么会失败?

最佳答案

你需要稍微改变你的策略,因为 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);
    }
}

关于为包含指针引用的已分配内存的结构释放内存的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38904871/

相关文章:

c - 标准输入和标准输出的使用

c++ - 堆上整数 vector 和释放内存

delphi - 释放 TObjectList 时发生访问冲突

memory-management - 为什么在垃圾回收语言中不允许使用free()?

c - 如何从字符串中提取整数?

c++ - 如何计算读取文件时的百分比?

c - 传递给函数的指针没有更新

c - libuv分配的内存缓冲区重用技术

C - 带 2 个结构的销毁函数

c - 实现池内存 API - 处理 union