将字符串分配为结构成员时发生内存泄漏

时间:2019-03-29 15:28:56

标签: c string data-structures struct memory-leaks

我已经构建了一个函数,可以将节点插入到双向链接列表中。该结构包括2个字符串,为此我在函数内部动态分配空间。根据Valgrind,这会导致内存泄漏。这是我的代码的简化版本:

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;
      }  
  }

在使用完列表之后,我正在main()内部使用destroy函数。这还不够吗?我是否应该以某种方式释放add函数中的字符串?

我在程序中反复使用此功能,因此会造成大约10.0000字节的丢失。您能告诉我为什么会发生这种内存泄漏吗?如何消除它?

1 个答案:

答案 0 :(得分:0)

您的add函数mallocNode,将其链接到列表,然后出于某种原因free是分配的Node。这样会将悬空的指针留在列表中。

您的add函数也没有机制将第一个Node添加到空白列表。有两种方法可以做到这一点。第一种方法是将指针返回到列表的第一个节点:

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;
}

使用第一种方法的示例调用:

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

第二种方法是将第一个参数更改为指向列表开头的指针:

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;
    }
}

使用第二种方法的示例调用:

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