【问题标题】:Freeing memory with a struct pointing to another struct使用指向另一个结构的结构释放内存
【发布时间】:2021-05-18 19:43:02
【问题描述】:

我在此处已多次看到此主题,但无法完全找到可以帮助我的信息。我正在努力为我的编程课释放内存来变得更好。我有下面的代码来分配一些内存,但不太明白如何释放它。我获取成员数量,分配那么多成员,然后分配每个成员评价过的葡萄酒的数量,并将他们评价过的每种葡萄酒的信息存储在通过我的成员链接链接的另一个结构中。

如何为这种特定风格的程序释放内存?

我注释掉了用于显示输入到程序中的信息的 printf 语句。任何帮助表示赞赏。

#include <stdio.h>
#include <stdlib.h>

typedef struct wine {
    char type[20];
    char brand[20];
    int rating;
} wine;

typedef struct member {
    char name[20];
    int numRated;
    wine* list;
} member;

int main()
{
    int n;
    
    scanf("%d", &n);
    
    member *members = malloc(n * sizeof(member));
    
    for(int i=0; i<n; i++){
        scanf("%s", (members+i)->name);
        scanf("%d", &(members+i)->numRated);
        (members+i)->list = malloc((members+i)->numRated * sizeof(wine));
        
        for(int j=0; j<(members+i)->numRated; j++){
            scanf("%s", (members+i)->list[j].type);
            scanf("%s", (members+i)->list[j].brand);
            scanf("%d", &(members+i)->list[j].rating);
            
        }
    }
    
    // for(int i=0; i<n; i++){
    //     printf("%s: %d\n", (members+i)->name, (members+i)->numRated);
    //     for(int j=0; j<(members+i)->numRated; j++){
    //         printf("Type:%s  Brand: %s  Rating: %d\n", (members+i)->list[j].type, (members+i)->list[j].brand, (members+i)->list[j].rating);
    //     }
    //     printf("\n");
    // }

    

    return 0;
}

编辑:提出一个明确的问题。

【问题讨论】:

  • 此代码中需要 n+1 个空闲:您在循环中分配的项目,以及您为成员分配的 1 个项目。简而言之,如果你有一个 malloc/realloc/calloc/strdup,迟早你需要一个 free 来匹配它。
  • @Barmar 是的,这是一种有效的表达方式。有什么区别吗?这段代码不适合在任何地方上交,所以只是测试一种不同的方式。
  • @KonradRudolph 你是对的。但这就是为什么我提倡只使用数组索引,它不那么令人困惑。
  • 回到您的问题,枚举您的序列并释放您分配的所有list 成员,然后释放成员序列本身。 IE。我之前提到的 n+1 分配。
  • 这真的很简单:任何你 malloc 的东西,你都应该在以后释放。所以如果你这样做(members+i)-&gt;list = malloc((members+i)-&gt;numRated * sizeof(wine));,你最终必须free((members+i)-&gt;list);

标签: c memory dynamic-memory-allocation


【解决方案1】:

解决方案:

在代码的底部,您将首先释放每个成员的葡萄酒评级,然后释放成员列表本身:

for (int i = 0; i < n; i++) {
    free(members[i].list); // Or free((members + i)->list;
}
free(members);

一般来说,每次调用malloc 时,您都应该有一个匹配的free 调用。

多一点解释:

第一次调用malloc 分配一个内存块来保存n 成员的信息。尽管这块内存可以存储n 成员的信息,但它仍然只是一块内存,只需调用一次 free 就会被释放。

在您的循环中,您为每个成员(n 次)分配一块内存,用于存储他们的葡萄酒评级信息。即使一个成员有很多葡萄酒评级,该成员的葡萄酒评级仍然只有一个内存块,因此您需要拨打free 的次数与拥有葡萄酒评级的成员一样多。

另外,请注意对free 的调用是如何以与对malloc 的调用相反的顺序发生的。这在直觉上是有道理的,你会想在释放 members 之前释放 members[i].list

【讨论】:

  • 我最初的释放尝试肯定是过度考虑了。谢谢你的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-23
  • 2018-09-11
  • 1970-01-01
  • 2017-04-07
  • 1970-01-01
  • 2020-03-15
相关资源
最近更新 更多