Memory not freed after calling free()

房东的猫 提交于 2019-11-26 23:41:54

问题


I have a short program that generates a linked list by adding nodes to it, then frees the memory allocated by the linked list.

Valgrind does not report any memory leak errors, but the process continues to hold the allocated memory.

I was only able to fix the error after I changed the memory allocated from sizeof(structure_name) to fixed number 512. (see commented code)

Is this a bug or normal operation? Here is the code:

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

回答1:


If by "the process continues to hold the allocated memory" you mean that ps doesn't report a decrease in the process's memory usage, that's perfectly normal. Returning memory to your process's heap doesn't necessarily make the process return it to the operating system, for all sorts of reasons. If you create and destroy your list over and over again, in a big loop, and the memory usage of your process doesn't grow without limit, then you probably haven't got a real memory leak.

[EDITED to add: See also Will malloc implementations return free-ed memory back to the system? ]

[EDITED again to add: Incidentally, the most likely reason why allocating 512-byte blocks makes the problem go away is that your malloc implementation treats larger blocks specially in some way that makes it easier for it to notice when there are whole pages that are no longer being used -- which is necessary if it's going to return any memory to the OS.]




回答2:


I discovered the answer to my question here:

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

The memory after expanding the heap can be returned back to kernel if the conditions configured by __noshrink are satisfied. Only then the ps will notice that the memory is freed.

It is important to configure it sometimes particularly when the memory usage is small, but the heap size is bigger than the main memory available. Thus the program trashes even if the required memory is less than the available main memory.



来源:https://stackoverflow.com/questions/5365996/memory-not-freed-after-calling-free

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!