【问题标题】:valgrind error in freeing memory of a linked list释放链表内存时的 valgrind 错误
【发布时间】:2020-12-04 17:18:27
【问题描述】:

我正在熟悉链表和动态内存。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
    char *name;  // name of student
    char ID[7];  // student ID (nul terminated)
    // you may add fields to this structure if needed
} Student;

typedef struct Course_st {
    // add fields here
    Student *Student_list;
    struct Course * next;
} Course;


// kirjoita ohjelma tähän

int main()
{
    Course *course_1 = (Course*)malloc(1*sizeof(Course));

    Student *st_1 =malloc(sizeof(Student));
    st_1->name = malloc(5*sizeof(char));
    strcpy(st_1->name,"Hien");
    strcpy(st_1->ID,"001");

    course_1->Student_list = st_1;
    course_1->next = malloc(sizeof(Course));

    Student *st_2 = malloc(4*sizeof(Student));
    st_2->name = malloc(4*sizeof(char));
    strcpy(st_2->name,"Kim");
    strcpy(st_2->ID,"002");
    
    Course* next = (Course*) course_1->next;
    next->Student_list = st_2;
    next->next= NULL;

    while(course_1 != NULL)
    {
        printf("%s %s\n", course_1->Student_list->name, course_1->Student_list->ID);
        free(course_1->Student_list->name);
        free(course_1->Student_list);
        course_1 = (Course*)course_1->next;
    }
    free(next);
}

我得到了这个错误...

退出时使用:1 个块中的 16 个字节

总堆使用量:7 次分配,6 次释放,分配 4,217 字节

1个block中的16个字节肯定会丢失在loss record 1 of 1中

在 0x4C2FB0F:malloc(在 /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so 中)

通过 0x1086EB:主要 (teht3.c:21)

泄漏摘要:

肯定会丢失:1 个块中的 16 个字节

...

对于检测到和抑制的错误计数,重新运行:-v

错误摘要:来自 1 个上下文的 1 个错误(已抑制:来自 0 的 0)

【问题讨论】:

  • 程序在第 21 行分配了一些东西,但它从未释放它。

标签: c linked-list valgrind dynamic-memory-allocation


【解决方案1】:

我会像这样改变你程序的结尾

        Course *old_course_1=course_1;
        course_1 = (Course*)course_1->next;
        free(old_course_1);
    }
    // free(next);

这样,您在考虑下一个时立即释放course_1;就这样 不需要最后一次调用free(next)

您正确地释放了course_1 的动态部分,但没有 course_1 自己。

【讨论】:

    【解决方案2】:

    您使用malloc(...) 分配的所有内容也应该使用free(...) 发布。在您的情况下,您不会释放 course_1。所以解决方案应该是:

    Course * tmp = course_1;
    Course * tmp_next;    
    
    while(tmp != NULL)
    {
        printf("%s %s\n", tmp->Student_list->name, tmp->Student_list->ID);
        free(tmp->Student_list->name);
        free(tmp->Student_list);
        tmp_next = tmp->next;
        free(tmp);
        tmp = tmp_next;
    }
    

    【讨论】:

    • 应该可以。或者,OP 可以简单地声明一个常规的Course 对象,而不是为一个动态分配内存,并将其地址分配为course_1 的初始值。那么就不需要释放(也不可能)。
    • 非常感谢您的帮助。现在可以了。我还有一个问题我需要(如果有必要的话)为tmp 变量分配内存吗?
    • 不客气。 tmp 只是一个指向Course 类型对象的指针,你不需要分配任何东西。在循环中遍历链表时,tmp 只是指向链表中的当前Course 对象,您之前已经为其分配了内存。
    猜你喜欢
    • 1970-01-01
    • 2013-12-23
    • 2023-03-04
    • 2012-06-12
    • 2021-03-29
    • 2014-09-19
    • 2021-07-09
    • 1970-01-01
    • 2018-06-04
    相关资源
    最近更新 更多