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

时间:2019-01-17 00:00:24

标签: c struct linked-list free ls

这是上学的。

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

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

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

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指针是不够的,但是我尝试了其他方法,但它不起作用。如果我尝试免费喜欢

free(entries->content->filename);

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

如果有人可以提示我如何正确释放这些列表,那真是太棒了,因为我真的很坚持。提前致谢。 抱歉,如果我的英语或解释不够清楚。

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

2 个答案:

答案 0 :(得分:1)

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

#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;
}

答案 1 :(得分:0)

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

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收到的副本无论如何都不会更改列表地址-而且因为完成后没有列表,但是使用临时节点(在任何函数中)遍历列表是更好的习惯,因此在处理实际列表地址时,不要混淆环境(例如,参数为{ {1}}或指针的副本(参数为t_list **)。

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