简体   繁体   中英

Memory leak when allocating strings as struct members

I have built a function to insert a node into a doubly-linked list. The structure includes 2 strings, for which I am dynamically allocating space inside the function. According to Valgrind, this causes a memory leak. Here is a simplified version of my code:

typedef struct Node {
    char *str1, *str2;
    Node *next, *prev;
};

void add(Node* list, char* string1, char* string2) {         
   Node* temp = list;
   Node* new_node = (Node*) malloc(sizeof(Node));
   if (!new_node) return;

   new_node->str1 = (char*) malloc(30*sizeof(char));
   new_node->str2 = (char*) malloc(30*sizeof(char));
   strcpy(new_player->str1, string1);
   strcpy(new_player->str2, string2);

   if (!temp) {
      temp = new_node;
      new_node->prev = new_node->next = NULL;
      new_node = NULL;
      free(new_node);
      return;
   } else {
       while (temp->next) temp = temp->next;

       new_node->prev = temp;
       new_node->next = NULL;
       temp->next =new_node;

       new_node = NULL;
       free(new_node);
   }

   void destroy(Node* list) {
      Node* temp;
      while (list) {
         temp = list->next;
         free(list->str1); 
         free(list->str2);
         free(list); 
         list = temp;
      }  
  }

I am using the destroy function inside of main() after having finished working with the list. Is that not enough? Am I supposed to somehow free the strings inside the add function?

I am using this function repeatedly in my program so it causes a loss of around 10.0000 bytes. Can you please tell me why this memory leak occurs and how can I get rid of it?

Your add function malloc sa Node , links it into the list and then free s the allocated Node for some reason. That will leave dangling pointers in the list.

Your add function also has no mechanism to add the first Node to an empty list. There are two ways that you could do that. The first way is to return a pointer to the first node of the list:

Node* add(Node* list, char* string1, char* string2) {         
    Node* temp = list;
    Node* new_node = malloc(sizeof(Node));
    if (!new_node) return NULL;

    new_node->str1 = malloc(strlen(string1)+1);
    new_node->str2 = malloc(strlen(string2)+1);
    if (!new_node->str1 || !new_node->str2) {
        // allocation error for one of the strings
        free(new_node->str1);
        free(new_node->str2);
        free(new_node);
        return NULL;
    }

    strcpy(new_node->str1, string1);
    strcpy(new_node->str2, string2);
    new_node->next = NULL;

    if (!temp) {
        new_node->prev = NULL;
        list = new_node;
    } else {
        while (temp->next) temp = temp->next;

        new_node->prev = temp;
        temp->next = new_node;
    }

    // return pointer to first node
    return list;
}

Example call using the first way:

Node* mylist = NULL;
...
mylist = add(mylist, "hello", "world");

The second way is to change the first parameter to a pointer to a pointer to the start of the list:

void add(Node** list, char* string1, char* string2) {         
    Node* temp = *list;
    Node* new_node = malloc(sizeof(Node));
    if (!new_node) return;

    new_node->str1 = malloc(strlen(string1)+1);
    new_node->str2 = malloc(strlen(string2)+1);
    if (!new_node->str1 || !new_node->str2) {
        // allocation error for one of the strings
        free(new_node->str1);
        free(new_node->str2);
        free(new_node);
        return;
    }

    strcpy(new_node->str1, string1);
    strcpy(new_node->str2, string2);
    new_node->next = NULL;

    if (!temp) {
        new_node->prev = NULL;
        *list = new_node;
    } else {
        while (temp->next) temp = temp->next;

        new_node->prev = temp;
        temp->next = new_node;
    }
}

Example call using the second way:

Node* mylist = NULL;
...
add(&mylist, "hello", "world");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM