title: Help with malloc and free: Glibc detected: free(): invalid pointer
body: <p>I need help with debugging this piece of code. I know the problem is in malloc and free but can't find exactly where, why and how to fix it. Please don't answer: "Use gdb" and that's it. I would use gdb to debug it, but I still don't know much about it and am still learning it, and would like to have, in the meanwhile, another solution.</p>
  
  <p>Thanks.</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;ctype.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;string.h&gt;
  #include &lt;sys/wait.h&gt;
  #include &lt;sys/types.h&gt;
  
  #define MAX_COMMAND_LENGTH  256
  #define MAX_ARGS_NUMBER     128
  #define MAX_HISTORY_NUMBER  100
  
  #define PROMPT "&gt;&gt;&gt; "
  
  int num_elems;
  
  typedef enum {false, true} bool;
  
  typedef struct {
      char **arg;     
      char *infile;   
      char *outfile;  
      int background; 
  } Command_Info;
  
  int parse_cmd(char *cmd_line, Command_Info *cmd_info)
  {
      char *arg;
      char *args[MAX_ARGS_NUMBER];    
  
      int i = 0;
      arg = strtok(cmd_line, " ");
      while (arg != NULL) {
          args[i] = arg;
          arg = strtok(NULL, " ");
          i++;
      }
  
      num_elems = i;precisa em free_mem
      if (num_elems == 0)
          return 0;
  
      cmd_info-&gt;arg = (char **) ( malloc(num_elems * sizeof(char *)) );
      cmd_info-&gt;infile = NULL;
      cmd_info-&gt;outfile = NULL;
      cmd_info-&gt;background = 0;
  
      bool b_infile = false;
      bool b_outfile = false;
  
      int iarg = 0;
      for (i = 0; i &lt; num_elems; i++)
      {                   
          if ( !strcmp(args[i], "&lt;") )
          {               
              if ( b_infile || i == num_elems-1 || !strcmp(args[i+1], "&lt;") || !strcmp(args[i+1], "&gt;") || !strcmp(args[i+1], "&amp;") )
                  return -1;                      
  
              i++;
              cmd_info-&gt;infile = malloc(strlen(args[i]) * sizeof(char));
              strcpy(cmd_info-&gt;infile, args[i]);
              b_infile = true;
          }
  
          else if (!strcmp(args[i], "&gt;"))
          {
              if ( b_outfile || i == num_elems-1 || !strcmp(args[i+1], "&gt;") || !strcmp(args[i+1], "&lt;") || !strcmp(args[i+1], "&amp;") )
                  return -1;
  
              i++;    
              cmd_info-&gt;outfile = malloc(strlen(args[i]) * sizeof(char));
              strcpy(cmd_info-&gt;outfile, args[i]);
              b_outfile = true;
          }
  
          else if (!strcmp(args[i], "&amp;"))
          {
              if ( i == 0 || i != num_elems-1 || cmd_info-&gt;background )
                  return -1;
  
              cmd_info-&gt;background = true;
          }
  
          else
          {
              cmd_info-&gt;arg[iarg] = malloc(strlen(args[i]) * sizeof(char));
              strcpy(cmd_info-&gt;arg[iarg], args[i]);
              iarg++;
          }
      }
  
      cmd_info-&gt;arg[iarg] = NULL; 
  
      return 0;
  }
  
  
  void print_cmd(Command_Info *cmd_info)
  {
      int i;  
      for (i = 0; cmd_info-&gt;arg[i] != NULL; i++)
          printf("arg[%d]=\"%s\"\n", i, cmd_info-&gt;arg[i]);
      printf("arg[%d]=\"%s\"\n", i, cmd_info-&gt;arg[i]);    
      printf("infile=\"%s\"\n", cmd_info-&gt;infile);
      printf("outfile=\"%s\"\n", cmd_info-&gt;outfile);
      printf("background=\"%d\"\n", cmd_info-&gt;background);
  }
  
  void get_cmd(char* str)
  {
      fgets(str, MAX_COMMAND_LENGTH, stdin);
      str[strlen(str)-1] = '\0';
  }
  
  pid_t exec_simple(Command_Info *cmd_info)
  {
      pid_t pid = fork();
  
      if (pid &lt; 0)
      {
          perror("Fork Error");
          return -1;
      }
  
      if (pid == 0)
      {
          if ( (execvp(cmd_info-&gt;arg[0], cmd_info-&gt;arg)) == -1)
          {
              perror(cmd_info-&gt;arg[0]);
              exit(1);
          }
      }
  
      return pid;
  }
  
  void type_prompt(void)
  {
      printf("%s", PROMPT);
  }
  
  void syntax_error(void)
  {
      printf("msh syntax error\n");
  }
  
  void free_mem(Command_Info *cmd_info)
  {
      int i;
      for (i = 0; cmd_info-&gt;arg[i] != NULL; i++)
          free(cmd_info-&gt;arg[i]);
      free(cmd_info-&gt;arg);
      free(cmd_info-&gt;infile);
      free(cmd_info-&gt;outfile);
  }
  
  int main(int argc, char* argv[])
  {
      char cmd_line[MAX_COMMAND_LENGTH];
      Command_Info cmd_info;
      //char* history[MAX_HISTORY_NUMBER];
  
      while (true)
      {   
          type_prompt();
  
          get_cmd(cmd_line);
  
          if ( parse_cmd(cmd_line, &amp;cmd_info) == -1)
          {
              syntax_error();
              continue;
          }
  
          if (!strcmp(cmd_line, ""))
              continue;
  
          if (!strcmp(cmd_info.arg[0], "exit"))
              exit(0);
  
          pid_t pid = exec_simple(&amp;cmd_info);
  
          waitpid(pid, NULL, 0);
  
          free_mem(&amp;cmd_info);
      }
  
      return 0;
  } 
  </code></pre>