1

I know that for every malloc there must be a free(), but in case of an existing linkedlist passed in a recursive function to insert a new node inside the linkedlist how would you free that? I'm using valgrind and it shows me that i must free the malloc

So my function has as parameters a char * and the pointer to the list passed as **, I did some research and it was needed to be passed like this in order to get the new nodes inserted even tho a pointer only worked well

void showDir(char *name, linkedList **list) {
    DIR *dir;
    struct dirent *entry;

    if (!(dir = opendir(name))) return;

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) {
            char path[1024];
            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
                continue;
            snprintf(path, sizeof(path), "%s/%s", name, entry->d_name);
            showDir(path, list);
        }
        linkedList *node = malloc(sizeof(linkedList));
        if (!node) {
            printf("Error!");
        }
        node->next = NULL;
        char filePath[1024];
        snprintf(filePath, sizeof(filePath), "%s/%s", name, entry->d_name);
        node->path = malloc(strlen(filePath) + 1);
        strcpy(node->path, filePath);
        if (*list) {
            int found = 0;
            for (linkedList *ptr = *list; ptr != NULL; ptr = ptr->next) {
                if (strcmp(ptr->path, filePath) == 0) {
                    found = 1;
                }
                if (ptr->next == NULL && found == 0) {
                    ptr->next = node;
                    break;
                }
            }
        } else {
            *list = node;
        }
    }
    closedir(dir);
}

I'm calling the recursive function like this showDir(ptr->path, &list); and freeing it like this

linkedList *ptr = list;
    while (ptr != NULL) {
        linkedList *next = ptr->next;
        free(ptr->path);
        free(ptr);
        ptr = next;
    }

Of course the list passed in the initial call is already filled up!

Thanks for the reading and hope you can help to understand what I'm doing wrong in here!

--EDIT

==1914== 64 (24 direct, 40 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 14
==1914==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1914==    by 0x10A633: showDir(filestat.c:512)
==1914==    by 0x10A629: showDir(filestat.c:510)
==1914==    by 0x10A629: showDir(filestat.c:510)
==1914==    by 0x109581: main (filestat.c:186)
Rasputin
  • 41
  • 3
  • 1
    Don't know if that's what you're running into (include the Valgrind report), but it appears that you don't free the newly allocated node if it's found. – 500 - Internal Server Error Jul 04 '19 at 18:57
  • The function `showDir` right now does not seem to be calling it self recursively. But to answer your question, unless there's some reallocation going on, you can easily free the list after the function call. You can also free when you do reallocation inside the function. – sassy_rog Jul 04 '19 at 18:59
  • @500-InternalServerError Included the valgrind report. – Rasputin Jul 04 '19 at 19:07
  • @SASSY_ROG What do you mean with I can easily free the list after the function call? I need the list for later use and can't free it, if i free the node after allocating it and inserting inside the linkedlist it will segment fault. – Rasputin Jul 04 '19 at 19:08
  • What is the state of `list` prior to the call `showDir(ptr->path, &list);`? Amend post and provide a [mcve] – chux - Reinstate Monica Jul 04 '19 at 21:16
  • Aside: Om success, `snprintf(filePath, sizeof(filePath), "%s/%s", name, entry->d_name);` returns the length of `filePath`. No need to call `strlen(filePath)` in the next line. Better to test that return value too for success. `int len = snprintf(filePath, sizeof filePath ,...); if (len < 0 || (unsigned) len >= sizeof filePath) Handle_error();` – chux - Reinstate Monica Jul 04 '19 at 21:18
  • After your `for` loop, if `found == 1` you might wanna free both `node->path` and `node` as they did not get added to the list. Also, as soon as the path is found, you can break out of the for loop, don;t have to check the remainder of the list. – rsp Mar 08 '21 at 16:37

2 Answers2

1

Create a tmp pointer. This way as you free them you can still move though the struct.

If you don't create a temp pointer to the address of the struct you are losing access to the rest of the nodes.

    void freeList(struct node* head)
{
   struct node* tmp;

   while (head != NULL)
    {
       tmp = head;
       head = head->next;
       free(tmp);
    }

}

C: How to free nodes in the linked list?

1

To free a Linkedlist recursively you can do it as follows:

void freeList(struct node* head){
    if(head != NULL){
      freeList(head->next);
      free(head);
    }
}
dreamcrash
  • 47,137
  • 25
  • 94
  • 117