包含结构的自由链表包含结构

Free linked list containing structures containing structures

这是给学校的。

我正在研究 Unix 'ls' 命令的实现。为此,我每次读取目录时都使用链表(如果未设置 -R 选项,则只使用一次)。为此,我必须使用链表函数和节点(或元素,我不确定正确的名称是什么。)我们必须在以前的项目中编写代码。这些节点看起来像这样:

typedef struct s_list
{
    void          *content;
    size_t         content_size;
    struct s_list *next;
}t_list;

在我的 ls 程序中,我使用这些来存储我列出的目录中的每个文件的名称和统计信息,这些信息是通过 stat() 函数获得的。所以我的t_list的'content'指针是这个结构:

typedef struct s_entry
{
    char       *filename;
    struct stat filestat;
}t_entry;

一切正常,我遇到的唯一问题是 Valgrind 告诉我用于分配那些 t_entry 结构的 malloc() 存在泄漏。所以我想我释放它们是错误的。我是这样做的:

void    free_list(t_list *entries)
{
    t_list *n_node;

    if (!entries)
        return ;
    while (entries)
    {
        n_node = entries->next;
        free(entries->content);
        free(entries);
        entries = n_node;
    }
}

我猜仅仅释放 *content 指针是不够的,但我尝试了其他方法,但它不起作用。如果我尝试释放 like

free(entries->content->filename);

例如,它不起作用,内容是空指针这一事实在我试图解决问题的某些方面似乎是个问题,但这就是我们必须对这些链表进行编码的方式函数。

如果有人能给我一些关于如何正确释放这些列表的提示,那就太棒了,因为我真的坚持这一点。提前致谢。 对不起,如果我的英语或解释不够清楚。

ps:为了以防万一,整个项目(远未完成)可以在这里找到: https://github.com/Zestx/ft_ls

您需要转换数据以便编译器知道在哪里可以找到结构成员,这里是一个完整的示例:

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

typedef struct s_list
{
    void          *content;
    size_t         content_size;
    struct s_list *next;
}t_list;

typedef struct s_entry
{
    char       *filename;
    struct stat filestat;
}t_entry;

int main(void)
{
    t_list *foo = malloc(sizeof *foo);
    t_entry *bar = malloc(sizeof *bar);
    bar->filename = malloc(10);
    foo->content = bar;

    free(((t_entry *)foo->content)->filename);
    free(foo->content);
    free(foo);

    return 0;
}

如果您有目录中每个文件的 ls 条目列表,其中 content 是指向包含文件名和 stat 信息的已分配 t_entry 的指针,例如

typedef struct s_list {
    void          *content;
    size_t         content_size;
    struct s_list *next;
} t_list;

typedef struct s_entry {
    char       *filename;
    struct stat filestat;
} t_entry;

freelist (t_list *head) 函数需要遍历每个节点,并且:

  1. free filename 分配在每个 t_entry 内;
  2. free分配t_entry;最后
  3. free t_list 节点本身。

您可以执行类似以下操作:

void freelist (t_list *head)
{
    t_list *node = head;        /* temporary node to iterate list  */
                                /* (you could use head, but don't) */
    while (*node) {
        t_list *victim = node;  /* pointer to current node to free */
        t_entry *entry = node->content;     /* pointer to content */

        free (entry->filename)  /* free content->filename */
        free (entry);           /* free t_entry struct itself */

        node = node->next;      /* advance before freeing victim */

        free (victim);          /* free current t_list node (victim) */
    }
}

注意上面,而不是使用 node,你可以简单地使用 head 来迭代,因为 freelist 收到一个无论如何都不会改变列表地址的副本——并且因为那里完成后将没有列表,但是使用临时节点迭代列表(在任何函数中)是一个更好的习惯,这样您在处理实际列表地址(例如参数是 t_list **) 或指针的副本(参数是 t_list *)。

检查一下,如果您还有其他问题,请告诉我。