Память не освобождается после вызова free () - PullRequest
2 голосов
/ 20 марта 2011

У меня есть короткая программа, которая генерирует связанный список, добавляя к нему узлы, а затем освобождает память, выделенную связанным списком.

Valgrind не сообщает об ошибках утечки памяти, но процесс продолжает удерживать выделенную память.

Мне удалось исправить ошибку только после того, как я изменил память, выделенную из sizeof (имя_структуры) на фиксированное число 512. (см. Прокомментированный код)

Это ошибка или нормальная работа? Вот код:

#include <execinfo.h>
#include <stdlib.h>
#include <stdio.h>


typedef struct llist_node {
  int ibody;
  struct llist_node * next;
  struct llist_node * previous;
  struct llist * list;
}llist_node;

typedef struct  llist {
  struct llist_node * head;
  struct llist_node * tail;
  int id;
  int count;
}llist;

llist_node * new_lnode (void) {
  llist_node * nnode = (llist_node *) malloc ( 512 );
  //  llist_node * nnode = (llist_node *) malloc ( sizeof(llist_node) );
  nnode->next = NULL;
  nnode->previous = NULL;
  nnode->list = NULL;
  return nnode;
}

llist * new_llist (void) {
  llist * nlist = (llist *) malloc ( 512 );
  //  llist * nlist = (llist *) malloc ( sizeof(llist) );
  nlist->head = NULL;
  nlist->tail = NULL;
  nlist->count = 0;
  return nlist;
}

void add_int_tail ( int ibody, llist * list ) {
  llist_node * nnode = new_lnode();
  nnode->ibody = ibody;
  list->count++;
  nnode->next = NULL;
  if ( list->head == NULL ) {
    list->head = nnode;
    list->tail = nnode;
  }
  else {
    nnode->previous = list->tail;
    list->tail->next = nnode;
    list->tail = nnode;
  }
}

void destroy_list_nodes ( llist_node * nodes ) {
  llist_node * llnp = NULL;
  llist_node * llnpnext = NULL;
  llist_node * llnp2 = NULL;
  if ( nodes == NULL )
    return;
  for ( llnp = nodes; llnp != NULL; llnp = llnpnext ) {
    llnpnext = llnp->next;
    free (llnp);
  }
  return;
}

void destroy_list ( llist * list ) {
  destroy_list_nodes ( list->head );
  free (list);
}

int main () {
  int i = 0;
  int j = 0;
  llist * list = new_llist ();

  for ( i = 0; i < 100; i++ ) {
    for ( j = 0; j < 100; j++ ) {
      add_int_tail ( i+j, list );
    }
  }
  printf("enter to continue and free memory...");
  getchar();
  destroy_list ( list );
  printf("memory freed. enter to exit...");
  getchar();
  printf( "\n");
  return 0;
}

Ответы [ 2 ]

5 голосов
/ 20 марта 2011

Если «процесс продолжает удерживать выделенную память», вы имеете в виду, что ps не сообщает об уменьшении использования памяти процессом, это совершенно нормально. Возврат памяти в кучу вашего процесса не обязательно заставляет процесс возвращать ее операционной системе по разным причинам. Если вы создаете и уничтожаете свой список снова и снова, в большом цикле, и использование памяти вашим процессом не увеличивается без ограничений, то у вас, вероятно, нет реальной утечки памяти.

[ИЗМЕНЕНО для добавления: См. Также Вернут ли реализации malloc свободную память обратно в систему? ]

[ИЗМЕНЕНО еще раз, чтобы добавить: Кстати, наиболее вероятная причина, по которой выделение 512-байтовых блоков устраняет проблему, заключается в том, что ваша реализация malloc обрабатывает большие блоки специально каким-то образом, что облегчает ее замечание при целые страницы, которые больше не используются - это необходимо, если он собирается вернуть какую-либо память в ОС.]

2 голосов
/ 20 марта 2011

Я нашел ответ на свой вопрос здесь:

http://linuxupc.upc.es/~pep/OLD/man/malloc.html

Память после расширения кучи может быть возвращена обратно в ядро, если выполнены условия, настроенные с помощью __noshrink.Только тогда пс заметит, что память освобождена.

Важно настроить его иногда, особенно когда использование памяти мало, но размер кучи больше, чем доступная основная память.Таким образом, программа удаляется, даже если требуемая память меньше доступной основной памяти.

...