title: Using malloc and free in recursive file scanning function
body: <p>I am writing a function that takes in a file-path argument and scans through the directory structure and loads it into a tree. I'm using a recursive function I created called <code>scan_and_add_children(struct Node* root)</code> that takes in the root node. The idea is I loop through the files in a directory, add the current node to the tree, and, if it's a directory, I call my recursive function using the current node as the root to add all of that directories children as well. However, I keep getting a <code>malloc(): corrupted top size</code> error. I am wondering if the dynamically allocated memory in the <code>new_node_to_be_added</code> variable is being lost once I make my recursive call. I can't free the node before the call as it's being used in my recursive function. I am yet to add my function that free()'s the tree, however, I know this is not the issue as I set a break point at the end of main and my program breaks before it even gets out of the function. I'm not super experienced with dynamic memory managenemt so I am trying to use this exercise to get more practice. Can someone explain to me what's going wrong?</p>
  <p>Here's my main program:</p>
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;dirent.h&gt; 
  #include &lt;sys/stat.h&gt;
  #include &lt;string.h&gt;
  
  #include &quot;linkedlist.h&quot;
  
  void scan_and_add_children(struct Node*);
  int file_exists(char* path);
  struct List* create_list(int level);
  struct Node* create_node(int level, char* name);
  
  int main(int argc, char** argv) {
  
      if(argc != 2) {
          printf(&quot;You must specify one path\n&quot;);
          return(-1);
      }
      if(!file_exists(argv[1])) {
          printf(&quot;Path not found or not valid\n&quot;);
          return(-1);
      }
      struct stat filestat;
      int level = 1;
  
      struct Node* root = create_node(level, argv[1]);
      struct List* rootList = create_list(1);
      insert_tail(root, rootList);
      //printf(&quot;%s\n&quot;, root-&gt;name);
      stat(root-&gt;name, &amp;filestat);
      if(!S_ISDIR(filestat.st_mode)) {    //if root node is a file
          printf(&quot;Just a file\n&quot;);
          return 1;
      }
      else {
          scan_and_add_children(root);
      }
  }
  
  void scan_and_add_children(struct Node* root) {
      DIR* dir;
      struct dirent* current;
      struct stat filestat;
      struct Node* new_node_to_be_added;
  
      dir = opendir(root-&gt;name);
      if(dir == NULL)
      {
          perror(&quot;Unable to read directory&quot;);
          closedir(dir);
          return;
      }
      while((current = readdir(dir))) {
          if(current-&gt;d_name[0] == '.') {     //skip files and directories that begin with a .
              continue;
          }
  
          if(root-&gt;name[strlen(root-&gt;name)-1] != '/') {       //add in / in order to make opendir functions work
              root-&gt;name = strcat(root-&gt;name, &quot;/&quot;);
          }
          
          char* rootCopy = strdup(root-&gt;name);                //using root-&gt;name in strcat changes rootcopy and messes up absolute path
          char* absolute_path = strcat(rootCopy, current-&gt;d_name);
          //free(rootCopy);
          printf(&quot;%s\n&quot;, absolute_path);
          
          new_node_to_be_added = create_node(root-&gt;children-&gt;level, absolute_path);       //create node and add to root-&gt;children
          
          insert_tail(new_node_to_be_added, root-&gt;children);
          stat(new_node_to_be_added-&gt;name, &amp;filestat);
          //print_list(root-&gt;children);
          if(S_ISDIR(filestat.st_mode)) {        //if it is a directory, scan and add its children, using new node to be added as root
              scan_and_add_children(new_node_to_be_added);
          }
      }
      free(new_node_to_be_added);
      closedir(dir);
  }
  
  int file_exists(char* path) {
      DIR* dir = opendir(path);
      if(dir) {
          closedir(dir);
          return 1;
      }
      else return 0;
  }
  </code></pre>
  <p>linkedlist.h:</p>
  <pre><code>struct Node {
      int id;
      char* name;
      struct Node* next;
      struct List* children;
  };
  
  struct List {
      int level;
      int count;
      struct Node* head;
      struct Node* tail;
  };
  
  struct List* create_list(int level) {
      struct List* list = malloc(sizeof(struct List));
      if (list == NULL) {
          fprintf (stderr, &quot;%s: Couldn't create memory for the list; %s\n&quot;, &quot;linkedlist&quot;, strerror (errno));
          exit(-1);
      }
      list-&gt;head = NULL;
      list-&gt;tail = NULL;
      list-&gt;count = 0;
      list-&gt;level = level;
      return list;
  }
  
  struct Node* create_node(int level, char* name) {
      struct Node* node = malloc(sizeof(struct Node));
      if (node == NULL) {
          fprintf(stderr, &quot;%s: Couldn't create memory for the node; %s\n&quot;, &quot;linkedlist&quot;, strerror (errno));
          exit(-1);
      }
      node-&gt;name = strdup(name);
      node-&gt;next = NULL;
      node-&gt;children = create_list(level+1);
      return node;
  }
  
  void insert_tail(struct Node* node, struct List* list) {
      if(list-&gt;head == NULL) {
          list-&gt;head = node;
          list-&gt;tail = node;
          list-&gt;count = 1;
          node-&gt;id = list-&gt;count;
      }
      else {
          list-&gt;tail-&gt;next = node;
          list-&gt;tail = node;
          list-&gt;count++;
          node-&gt;id = list-&gt;count;
      }
  }
  
  void print_list(struct List* list) {
      struct Node* node = list-&gt;head;
      while(node != NULL) {
          if(node != list-&gt;head) {
              printf(&quot;-&gt;&quot;);
          }
          printf(&quot;%d&quot;, node-&gt;id);
          node = node-&gt;next;
      }
  }
  
  void destroy_list(struct List* list) {
      struct Node* node = list-&gt;head;
      struct Node* tmp;
      while(node != NULL) {
          tmp = node;
          node = node-&gt;next;
          destroy_node(tmp);
      }
      free(list);
  }
  
  void destroy_node(struct Node* node) {
      destroy_list(node-&gt;children);
      free(node-&gt;name);
  }
  </code></pre>
  <p>Output:</p>
  <pre><code>-Surface-Book-2:/home/projects/project1$ ./dirtree /home/projects/
  /home/projects/linked-li
  /home/projects/project1
  dirtree: malloc.c:2379: sysmalloc: Assertion `(old_top == initial_top (av) &amp;&amp; old_size == 0) || ((unsigned long) (old_size) &gt;= MINSIZE &amp;&amp; prev_inuse (old_top) &amp;&amp; ((unsigned long) old_end &amp; (pagesize - 1)) == 0)' failed.
  Aborted (core dumped)
  -Surface-Book-2:/home/projects/project1$ 
  </code></pre>