Search code examples
cmemorymemory-leaksstrdup

How to free the leak caused by strdup?


#include <assert.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

bool debugOpt=false;

int main (int argc, char **argv) {
   (void) argc;
   char *progname = basename (argv[0]);
   char err_buffer [256];
   char err_buf_fmt[16];

   int option=getopt(argc,argv,"d");
   if(option=='d') debugOpt=true;

   typedef struct node *Node;
   struct node {
      char *item;
      Node link;
   };
   Node head=NULL;

   char buffer[82];
   int ln;
   for(ln=1;;++ln){

      char *line=fgets(buffer,sizeof buffer, stdin);
      if(line==NULL) break;

      char *nlpos=strchr(buffer,'\n');
      if (nlpos!=NULL) *nlpos='\0';
       else{
           fprintf(stderr,"%s: %d: unterminated line: %s\n",
                   progname, ln, buffer);
       }

 Node tmp=malloc(sizeof (struct node));
 assert(tmp != NULL);
 if(tmp!=NULL) tmp->item = strdup (buffer); //leak here

         Node prev=NULL;
         Node curr=head;

           //find insertion point
         while(curr != NULL) {
              int cmp=strcmp(curr->item, tmp->item);
              if(cmp>0) break;
              prev=curr;
              curr=curr->link;
           }
           //do insertion
         tmp->link = curr;
         if (prev==NULL) head =tmp;
         else prev->link = tmp;
   }


//print the list
        Node cursor;
        for(cursor=head;cursor!=NULL;cursor=cursor->link){

         if(debugOpt==true)
             printf("%p -> struct node {item= %.15g, link=%p}\n", cursor, cursor->item, cursor->link);
         else
             printf("%s\n",cursor->item);
             }


      //free nodes
      while(head!=NULL){
          Node oldhead=head;
          head=head->link;
          free(oldhead);
      }


   return EXIT_SUCCESS;
}

basically this program read the lines and then print out in lexicographic order.

I see that the use of strdup(buffer) is causing a leak and I'm not freeing it.

when I put the statement

free(tmp->item)

, it shows that no leaks are possible. But it won't give correct output then. How should I deal with this leak?


Solution

  • You should free the item at the end of your program when you free the linked list:

      while(head!=NULL){
          free(head->item);  /* <-- Free the item here. */
          Node oldhead=head;
          head=head->link;
          free(oldhead);
      }