释放链表中的 strdup

Freeing a strdup inside of a linked list

我有一个链接列表,我试图在其中释放一个 char*,我将其用于 strdup

这些是我将节点添加到列表中的方法:

  node* add_first(char* name,  node* head) {
          node* new_node;
          new_node = (node*)malloc(sizeof(node));
          char* c = strdup(name);
          new_node->name = c;
          new_node->next = head;
          head = new_node;
          return head;
  }

node * add_last(char* name, node *head ) {
      node* new_node;
      node* current;
      new_node = (node*)malloc(sizeof(node));
      char* c = strdup(name);
      new_node->name = c;
      new_node->next = NULL;

      if ( head == NULL ){
              head = new_node;
      }
      else{
              current = head;
              while ( current->next ) current = current->next;
              current->next = new_node;
      }

          return head;
  }

删除节点:

 int remove_last( node **head, char **ret )
  {
          int result = *head == NULL ? -1 : 0;

          if ( result == 0 )
          {
                  while( ( *head )->next != NULL ) head = &( *head )->next;

                  *ret = strdup( ( *head )->name );
                  free( *head );
                  *head = NULL;
          }

          return result;
  }

清理列表:

void deleteList(node** head){
      node* current = *head;
      node* next;

      while(current != NULL){
              next = current->next;
              free(current->name);
              free(current);
              current = next;
      }

      *head = NULL;
  }

但是 valgrind 说,当涉及到 strdup 我的 add_last 函数(但奇怪的是我的 add_first 函数没有)时,我“肯定失去了”记忆。

为什么它只发生在 add_last 方法中,我该如何正确释放它?我以为我正在释放 deleteList 方法中的所有节点和名称?

您不必要地复制了最后一个节点删除算法中的字符串,并泄露了原始字符串。该算法应该找到列表中的最后一个节点,将 name 指针的所有权传递给输出参数,然后删除节点 而不会 删除名称(因为输出 -参数现在拥有它)。

即您应该按照这些思路做一些事情(公平警告,未经编译测试,但希望您能理解):

int remove_last( node **head, char **ret )
{
    int res = -1;
    if (*head)
    {
        // find last node in the list
        while ((*head)->next)
            head = &(*head)->next;

        // out-param takes ownership
        *ret =(*head)->name;

        // free last node *without* freeing the string
        free(*head);
        *head = NULL;

        // result indicates success
        res = 0;
    }
    return res;
}