Утечка памяти - Единственный связанный список в C - PullRequest
1 голос
/ 08 мая 2019

Я реализую этот простой код для реализации списка с одиночными связями на C. Я просто опубликовал еще один вопрос для этого кода ( ссылка ).Я поместил код так же, чтобы вы могли видеть его, не меняя страницы.Это код:

структура узла списка:

struct hash_table_key_list_node_s {
  char *key;
  struct hash_table_key_list_node_s* next;
};

typedef struct hash_table_key_list_node_s hash_table_key_list_node_t;
typedef hash_table_key_list_node_t* hash_table_key_list_t;

код функции:

hash_table_key_list_t hash_table_keys(hash_table_t hash_table) {

  hash_table_key_list_t list, tail, p;
  list = tail = NULL;

  if ( hash_table != NULL && hash_table->slots != NULL ) {

    size_t index = 0;
    while ( index < hash_table->capacity ) {

      hash_table_list_node_t *node = hash_table->slots[index].head;
      while ( node != NULL ) {

        p = malloc(sizeof(hash_table_key_list_node_t));
        p->key = malloc((strlen(node->key) + 2) * sizeof(char));
        if ( p->key == NULL ) {
          perror("Unable to allocate a key\n");
          abort();  
        }

        strcpy(p->key, node->key);

        if ( node != NULL ) {
          list = tail = p;
        }
        else { 
          tail->next = p;
          tail = p;
        }

        node = node->next;
      }

      index++;
    }
  }

  return list; 
}

функция для уничтожения списка

void destroy_key_list(hash_table_key_list_t key_list) {

  hash_table_key_list_node_t *current = NULL;

  if ( key_list == NULL ) return;

  while ( key_list != NULL ) {
    current = key_list;
    free(current->key);
    free(current);

    key_list = key_list->next;
  }

  free(key_list);
}

У меня есть две проблемы, которые я не понимаю:

  • Почему список больше не содержит узлов после использования списка, возвращаемого к функции?Это для типа списка?
  • Почему это вызывает у меня потерю памяти?Я попытался вызвать функцию free для переменной node, прежде чем увеличивать переменную index, но ничего не изменилось.

Это вывод valgrind после одного вызова функции:

==10757== HEAP SUMMARY:
==10757==     in use at exit: 15,840 bytes in 660 blocks
==10757==   total heap usage: 1,329 allocs, 669 frees, 123,642 bytes allocated
==10757== 
==10757== 5,264 bytes in 329 blocks are indirectly lost in loss record 1 of 3
==10757==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10757==    by 0x10B93E: hash_table_keys (in /media/psf/bioinformatics-assignment-1/app/main)
==10757==    by 0x109B27: main (in /media/psf/bioinformatics-assignment-1/app/main)
==10757== 
==10757== 10,560 bytes in 330 blocks are indirectly lost in loss record 2 of 3
==10757==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10757==    by 0x10B975: hash_table_keys (in /media/psf/bioinformatics-assignment-1/app/main)
==10757==    by 0x109B27: main (in /media/psf/bioinformatics-assignment-1/app/main)
==10757== 
==10757== 15,840 (16 direct, 15,824 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 3
==10757==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==10757==    by 0x10B93E: hash_table_keys (in /media/psf/bioinformatics-assignment-1/app/main)
==10757==    by 0x109B27: main (in /media/psf/bioinformatics-assignment-1/app/main)

Здесь вы можете найти все источники и заголовки файла:

  • hash_table.c (есть реализация всех функций)
  • hash_table_private.h (закрытый заголовок, где определение структуры)
  • hash_table.h (публичный заголовок, где прототип функции)

1 Ответ

2 голосов
/ 08 мая 2019

Осторожно здесь:

while ( key_list != NULL ) {
    current = key_list; // current is now a copy of key_list (a copy of the pointer)
    free(current->key);
    free(current);      // here you free current and hence key_list

    key_list = key_list->next; // here you are referring to key_list, just freed above
  }

Попробуйте вместо этого:

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

В вашем коде могут быть другие ошибки, но это была одна.

...