studio programacion para optimizar móviles libro lentas edición desarrollo curso consultas aplicaciones memory malloc free memory-leaks

memory - programacion - optimizar consultas lentas mysql



La memoria no se libera después de llamar a free() (2)

Tengo un programa corto que genera una lista vinculada añadiéndole nodos y luego libera la memoria asignada por la lista vinculada.

Valgrind no informa ningún error de pérdida de memoria, pero el proceso continúa reteniendo la memoria asignada.

Solo pude solucionar el error después de cambiar la memoria asignada de sizeof (structure_name) al número fijo 512. (ver código comentado)

¿Es esto un error o una operación normal? Aquí está el código:

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


Descubrí la respuesta a mi pregunta aquí:

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

La memoria después de expandir el montón puede devolverse al kernel si se cumplen las condiciones configuradas por __noshrink. Solo entonces el ps notará que la memoria se libera.

Es importante configurarlo algunas veces particularmente cuando el uso de la memoria es pequeño, pero el tamaño del almacenamiento dinámico es mayor que la memoria principal disponible. Por lo tanto, el programa se destruye incluso si la memoria requerida es menor que la memoria principal disponible.


Si por "el proceso continúa reteniendo la memoria asignada" quiere decir que ps no informa una disminución en el uso de la memoria del proceso, eso es perfectamente normal. Devolver la memoria al montón de su proceso no necesariamente hace que el proceso lo devuelva al sistema operativo, por todo tipo de razones. Si crea y destruye su lista una y otra vez, en un gran bucle, y el uso de memoria de su proceso no crece sin límite, entonces probablemente no tenga una pérdida de memoria real.

[EDITADO para agregar: Ver también ¿Las implementaciones de malloc devolverán la memoria de libre acceso al sistema? ]

[EDITADO de nuevo para agregar: Por cierto, la razón más probable por la cual la asignación de bloques de 512 bytes hace que el problema desaparezca es que la implementación de malloc trata bloques más grandes especialmente de alguna forma que hace que sea más fácil notar cuando hay páginas enteras que son ya no se usa, lo cual es necesario si va a devolver cualquier memoria al sistema operativo.]