title: C: free freeing more than I want
body: <p>I've asked a few questions about this before, but I think I've found the root cause of the problem.</p>
  
  <p>I have a program mainLex.c which contains this loop:</p>
  
  <pre><code>for (;;)  {
      printf ("(%d)$ ", ncmd);                // Prompt for command
      if ((line = getLine(stdin)) == NULL)    // Read line
          break;                              // Break on end of file
  
      cmd = hExpand (line, &amp;status);          // Expand line
      free (line);
      if (status &gt; 0)                         // Substitution?
          fputs (cmd, stdout);                //   Print expanded line
      else if (status &lt; 0)
          fputs ("substitution failed\n", stderr);
  
      list = lex (cmd);                       // Lex line into tokens
      free (cmd);
      if (list == NULL)                       // Empty token list?
          continue;
  
      hRemember (ncmd, list);                 // Remember command
      if (status &gt;= 0)                        // No substitution error?
          process (list);                     //   Process token list
  
      freeList (list);                        // Free token list
      ncmd++;                                 // Adjust prompt
      }
  </code></pre>
  
  <p>After running through the loop once, the method is supposed to free the list at freeList, then ask for a new string to use as list. This is all well and good, but I'm finding that freeList is freeing things that I'm not asking it to! In particular, it is freeing a global static data structure llist, and I'm not sure how this is happening.</p>
  
  <p>The code for freeList:</p>
  
  <pre><code>void freeList (token *list)
  {
      token *p, *pnext;
      for (p = list;  p;  p = pnext)  {
          pnext = p-&gt;next;
          free(p-&gt;text);
          free(p); //This is apparently where the data structure is being freed
      }
  }
  </code></pre>
  
  <p>hRemember:</p>
  
  <pre><code>void hRemember (int ncmd, token *list)
  {
      command* curr;
      curr = (struct command *)malloc(sizeof(struct command));
      token *list1 = malloc(sizeof(token));
      list1=list;
      f = ncmd;
      curr-&gt;cmmd=(struct token *)malloc(sizeof(struct token));
      curr-&gt;cmmd=list1;
      curr-&gt;num=ncmd;
      curr-&gt;prev=llist;
      if (llist==NULL)
      {
          llist = (struct command *)malloc(sizeof(struct command));
      }
      llist-&gt;nextcmd=curr;
      llist=curr;
  }
  </code></pre>
  
  <p>llist:</p>
  
  <pre><code>typedef struct command {          // Struct for each token in linked list
      token *cmmd;                   //   String containing token
      int num;                     //   Corresponding type
      struct command *prev;
      struct command *nextcmd;      //   Pointer to next token in linked list
  } command;
  
  
  command* llist = NULL; //This is global in a different c file than the loop
  </code></pre>
  
  <p>After I try to read llist's contents after one version of the loop, this is what comes up:</p>
  
  <pre><code>==12878== Invalid read of size 8
  ==12878==    at 0x400DB5: hDump (Lex1.c:153)
  ==12878==    by 0x400BA9: process (mainLex.c:66)
  ==12878==    by 0x400B0C: main (mainLex.c:41)
  ==12878==  Address 0x51f34f0 is 0 bytes inside a block of size 24 free'd
  ==12878==    at 0x4C29577: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==12878==    by 0x400C0E: freeList (mainLex.c:81)
  ==12878==    by 0x400B18: main (mainLex.c:43)
  ==12878== 
  ==12878== Invalid read of size 1
  </code></pre>
  
  <p>If possible, I would like to not change either the loop or freeList.</p>
  
  <p>EDIT: lex routine, which uses llist (I need to clean this up a lot, but it's functional as of now)</p>
  
  <pre><code>token *lex (const char *line)
  {
      if (strcspn(line, METACHARS)==strlen(line))
      {
          token *head, *temp, *right, *temp1;
          char *line1 = strdup(line);
          char *curr = separate(line1);
          temp = (token *)malloc(sizeof(token));
          temp-&gt;text=strdup(curr);
          temp-&gt;type=10;
          head=temp;
          head-&gt;next=NULL;
          curr=separate(NULL);
          while (curr!=NULL)
          {
              temp1 = (token *)malloc(sizeof(token));
              right = head;
              while (right-&gt;next != NULL)
              {
                  right=right-&gt;next;
  
              }
              temp1-&gt;text=strdup(curr);
              temp1-&gt;type=10;
              temp1-&gt;next=NULL;
              right-&gt;next=temp1;
              curr=separate(NULL);
          }
          return head;
      }
      else
      {
          token *head, *temp, *right, *temp1;
          char *line1 = strdup(line);
          char *curr = separate(line1);
          temp = (token *)malloc(sizeof(token));
          temp-&gt;text=strdup(curr);
          if (strcmp(temp-&gt;text,"&lt;")==0)
          {
              temp-&gt;type=20;
          }
          else if (strcmp(temp-&gt;text,"&lt;&lt;")==0)
          {
              temp-&gt;type=21;
          }
          else if (strcmp(temp-&gt;text,"|")==0)
          {
              temp-&gt;type=30;
          }
          else if (strcmp(temp-&gt;text,"&gt;")==0)
          {
              temp-&gt;type=31;
          }
          else if (strcmp(temp-&gt;text,"&gt;&gt;")==0)
          {
              temp-&gt;type=32;
          }
          else if (strcmp(temp-&gt;text,";")==0)
          {
              temp-&gt;type=40;
          }
          else if (strcmp(temp-&gt;text,"&amp;")==0)
          {
              temp-&gt;type=41;
          }
          else if (strcmp(temp-&gt;text,"&amp;&amp;")==0)
          {
              temp-&gt;type=42;
          }
          else if (strcmp(temp-&gt;text,"||")==0)
          {
              temp-&gt;type=43;
          }
          else if (strcmp(temp-&gt;text,"(")==0)
          {
              temp-&gt;type=50;
          }
          else if (strcmp(temp-&gt;text,")")==0)
          {
              temp-&gt;type=51;
          }
          else
          {
              temp-&gt;type=10;
          }
  
          head=temp;
          head-&gt;next=NULL;
          curr=separate(NULL);
          while (curr!=NULL)
          {
              temp1 = (token *)malloc(sizeof(token));
              right = head;
              while (right-&gt;next != NULL)
              {
                  right=right-&gt;next;
  
              }
              temp1-&gt;text=strdup(curr);
              if (strcmp(temp1-&gt;text,"&lt;")==0)
              {
                  temp1-&gt;type=20;
              }
              else if (strcmp(temp1-&gt;text,"&lt;&lt;")==0)
              {
                  temp1-&gt;type=21;
              }
              else if (strcmp(temp1-&gt;text,"|")==0)
              {
                  temp1-&gt;type=30;
              }
              else if (strcmp(temp1-&gt;text,"&gt;")==0)
              {
                  temp1-&gt;type=31;
              }
              else if (strcmp(temp1-&gt;text,"&gt;&gt;")==0)
              {
                  temp1-&gt;type=32;
              }
              else if (strcmp(temp1-&gt;text,";")==0)
              {
                  temp1-&gt;type=40;
              }
              else if (strcmp(temp1-&gt;text,"&amp;")==0)
              {
                  temp1-&gt;type=41;
              }
              else if (strcmp(temp1-&gt;text,"&amp;&amp;")==0)
              {
                  temp1-&gt;type=42;
              }
              else if (strcmp(temp1-&gt;text,"||")==0)
              {
                  temp1-&gt;type=43;
              }
              else if (strcmp(temp1-&gt;text,"(")==0)
              {
                  temp1-&gt;type=50;
              }
              else if (strcmp(temp1-&gt;text,")")==0)
              {
                  temp1-&gt;type=51;
              }
              else
              {
                  temp1-&gt;type=10;
              }
              temp1-&gt;next=NULL;
              right-&gt;next=temp1;
              curr=separate(NULL);
          }
          return head;
      }
  }
  </code></pre>