This is for school.
I'm working on an implementation of the Unix 'ls' command. For this I'm using linked lists each time I'm reading a directory (so only one time if the -R option is not set). For this I have to use the linked lists functions and nodes (or elements, I'm not sure what's the correct name.) that we had to code on a previous project. Those nodes looks like this:
typedef struct s_list
{
void *content;
size_t content_size;
struct s_list *next;
}t_list;
In my ls program, I use these to store, for each file in the directory I'm listing, it's name and it's stats, obtained with the stat() function. So the 'content' pointer of my t_list is this structure:
typedef struct s_entry
{
char *filename;
struct stat filestat;
}t_entry;
Everything works fine, the only problem I got is that Valgrind tell me there's a leak comming from the malloc() used to allocate those t_entry structures. So I guess I'm freeing them up wrong.. here's how I do it:
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;
}
}
I'm guessing it is not enough to just free the *content pointer, but I tried other ways and it wont works. If I try to free like
free(entries->content->filename);
for example, it doesn't works and the fact that the content is a void pointer seems to be a problem in some ways that I tried to resolve the problem, but that's the way we had to code those linked list functions.
If someone could give me an hint on how to free these lists correctly, It would be awesome as I'm really stuck on this. Thanks in advance. Sorry if my english or explanation isn't clear enough.
ps: Just in case, the whole project (far from finished) can be found here: https://github.com/Zestx/ft_ls
If you have your list of ls
entries for each file within a directory where content
is a pointer to an allocated t_entry
containing the filename and stat
information, e.g.
typedef struct s_list {
void *content;
size_t content_size;
struct s_list *next;
} t_list;
and
typedef struct s_entry {
char *filename;
struct stat filestat;
} t_entry;
A freelist (t_list *head)
function would need to iterate over each node, and:
free
the filename
allocated within each t_entry
; free
the allocated t_entry
; and finallyfree
the t_list
node itself.You could do something similar to the following:
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) */
}
}
Note above, instead of using node
, you could simply use head
to iterate since freelist
receives a copy that would not alter the list address anyway -- and since there will be no list left when you are done, but it is a far better habit to use a temporary node to iterate the list (in any function) so you do not confuse the circumstances when you are handling the actual list address (e.g. the parameter was t_list **
) or a copy of the pointer (the parameter was t_list *
).
Look things over and let me know if you have further questions.