有没有办法一次性释放结构的所有成员?

Is there a way to free all members of a struct which have been strdup'd all at once?

例如我有以下结构:

 struct Student{
     char *studentName;
     int studentAge;
     struct Student *next;
  };

我在链表中​​有许多 Student 结构实例(针对许多不同的学生)。结构中的每个变量都是 strdup'd(int 除外)。

现在,在完成我的程序准备执行的所有处理后,我想添加一个函数,该函数将释放所有结构实例并释放所有已被 strdup 的变量。有什么方法可以快速做到这一点吗?

为了使下面的工作正常,您需要将 strcut Student 中的 next 成员初始化为 NULL,这样基本上列表中的最后一个 link 将是 NULL:

void freeStudents (struct Student *cur)
{
    struct Student *tmp;
    while (cur != NULL)
    {
        tmp = cur->next;
        free (cur->studentName);
        free (cur);
        cur = tmp;
    }
}

不清楚您所说的 "in a quick manner" 或 "all at once" 是什么意思。我最好的猜测是您正在寻找一个标准库函数,该函数在一次调用中将自动释放您想要释放的所有内存。确实有这样一个函数:exit()。不幸的是,它的其他效果不太可能符合您的目的。

否则,没有标准库函数可以实现您所追求的。一般的标准库函数,特别是内存管理函数不理解你的 structs 的内容。例如,它们无法识别您的某些 struct 成员是可能也需要释放其引用对象的指针。即使他们能够检测到这一点,执行该释放对他们来说也是不安全的,因为他们不知道是否有任何其他指针指向同一动态内存。

解决此类问题的通常方法是编写您自己的函数来释放 struct 的实例,以及其中所有需要释放的成员。例如:

void free_student(struct Student *s) {
    free(s->studentName);
    free(s);
}

这有一个明显的优势,如果您修改了 struct,那么您可以适当地更改释放函数,而不是在多个地方更改 ad-hoc 释放代码。

您可以让这样的函数执行双重任务以递归地释放列表中的下一个学生,但是为此目的使用一个单独的函数(使用第一个函数)会更清晰:

void free_student_list(struct Student *head) {
    while (head) {
        struct Student *next = head->next;

        free_student(head);
        head = next;
    }
}

这种方法的前提是确定哪些成员可以并且应该被释放,因此您必须注意您打算释放的成员确实指向分配的内存,它们不会相互混淆,并且在程序的其他地方没有 presumed-valid 指向相同内存的指针。