Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
296 views
in Technique[技术] by (71.8m points)

malloc - Memory not freed after calling free()

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( "
");
  return 0;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.]


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...