Свободный связанный список, содержащий структуры, содержащие структуры - PullRequest
0 голосов
/ 17 января 2019

Это для школы.

Я работаю над реализацией команды 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 сказал мне, что есть утечка из-за malloc (), используемой для выделения этих структур t_entry. Итак, я думаю, что я освобождаю их неправильно .. вот как я это делаю:

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

Полагаю, недостаточно просто освободить указатель * содержимого, но я попробовал другие способы, и он не будет работать. Если я попытаюсь освободить, как

free(entries->content->filename);

например, это не работает, и тот факт, что содержимое является пустым указателем, кажется, является проблемой в некоторых отношениях, и я пытался решить эту проблему, но именно так мы должны были кодировать эти функции связанного списка.

Если бы кто-нибудь мог дать мне подсказку о том, как правильно освободить эти списки, это было бы здорово, потому что я действительно застрял в этом. Заранее спасибо. Извините, если мой английский или объяснение недостаточно ясны.

ps: На всякий случай весь проект (далеко не законченный) можно найти здесь: https://github.com/Zestx/ft_ls

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Если у вас есть список 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 получает копию, которая не изменит адрес списка в любом случае - и так как список не останется, когда вы готово, но гораздо лучше использовать временный узел для итерации списка (в любой функции), чтобы не путать обстоятельства, когда вы обрабатываете фактический адрес списка (например, параметр был t_list **) или копию указателя (параметр был t_list *).

Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 17 января 2019

Вам нужно привести данные так, чтобы компилятор знал, где найти члены структуры, вот полный пример:

#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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...