Pregunta

Por favor ayuda :) OS:linux

Donde en "sleep(1000);", en este momento "top (mostrar tareas de Linux)" me escribió un 7,7% de uso de MEM.valgrind:pérdida de memoria no encontrada.

Lo entiendo, escribí correctamente y todos los resultados de malloc son NULL.Pero, ¿por qué en este tiempo "dormir" mi programa NO disminuyó la memoria?¿Qué falta?

Perdón por mi mal inglés, gracias.


~ # tmp_soft
For : Is it free??  no
Is it free??  yes
For 0 
For : Is it free??  no
Is it free??  yes
For 1 
END : Is it free??  yes
END 

~ #top
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                
23060 root      20   0  155m 153m  448 S    0  7.7   0:01.07 tmp_soft    

Fuente completa:tmp_soft.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

struct cache_db_s
{
 int       table_update;
 struct    cache_db_s * p_next;
};

void free_cache_db (struct cache_db_s ** cache_db)
{
 struct cache_db_s * cache_db_t;
 while (*cache_db != NULL)
 {
  cache_db_t = *cache_db;
  *cache_db = (*cache_db)->p_next;
  free(cache_db_t);
  cache_db_t = NULL;
 }
 printf("Is it free??  %s\n",*cache_db==NULL?"yes":"no");
}

void make_cache_db (struct cache_db_s ** cache_db)
{
 struct cache_db_s * cache_db_t = NULL;
 int n = 10000000;

 for (int i=0; i = n; i++)
 {
  if ((cache_db_t=malloc(sizeof(struct cache_db_s)))==NULL) {
   printf("Error : malloc 1 -> cache_db_s (no free memory) \n");
   break;
  }
  memset(cache_db_t, 0, sizeof(struct cache_db_s));

  cache_db_t->table_update = 1; // tmp 

  cache_db_t->p_next = *cache_db;
  *cache_db = cache_db_t;
  cache_db_t = NULL;
 }
}

int main(int argc, char **argv)
{
 struct cache_db_s * cache_db = NULL;

 for (int ii=0; ii  2; ii++) {
  make_cache_db(&cache_db);
  printf("For : Is it free??  %s\n",cache_db==NULL?"yes":"no");
  free_cache_db(&cache_db);
  printf("For %d \n", ii);
 }

 printf("END : Is it free??  %s\n",cache_db==NULL?"yes":"no");
 printf("END \n");
 sleep(1000);
 return 0;
}
¿Fue útil?

Solución

Si está intentando establecer si su programa tiene una pérdida de memoria, entonces top no es la herramienta adecuada para el trabajo (valrind es).

top muestra el uso de la memoria tal como lo ve el sistema operativo.Incluso si llamas free, no hay garantía de que la memoria liberada se devuelva al sistema operativo.Normalmente, no sería así.No obstante, la memoria se vuelve "libre" en el sentido de que su proceso puede usarla para asignaciones posteriores.

editar Si tu libc lo admite, podrías intentar experimentar con M_TRIM_THRESHOLD.Incluso si sigue este camino, será complicado (un solo bloque usado ubicado cerca de la parte superior del montón evitaría que toda la memoria libre debajo de él se libere al sistema operativo).

Otros consejos

Por buenas razones, prácticamente ningún problema de memoria devuelve los bloques al sistema operativo

La memoria solo se puede eliminar de su programa en unidades de páginas, e incluso a eso es poco probable que se observe.

Calloc (3) y malloc (3) interactúan con el kernel para obtener memoria, si es necesario. Pero muy, muy pocas implementaciones de la memoria gratuita (3) de la historia, de alguna vez devolver el kernel 1 , simplemente lo agregan a una lista gratuita que Calloc () y Malloc () consultarán más adelante para reutilizar el Bloques liberados. Hay buenas razones para este enfoque de diseño.

Incluso si es gratuito () quería devolver la memoria al sistema, necesitaría al menos una página de memoria contigua para que el kernel proteja realmente a la región, así que la liberación de un bloque pequeño solo conduciría a un cambio de protección. Si fue el bloque pequeño Último en una página.

Teoría de la Operación

SO MALLOC (3) obtiene memoria del kernel cuando lo necesita, en última instancia, en unidades de múltiplos de página discretos. Estas páginas están divididas o consolidadas como lo requiere el programa. Malloc y cooperar gratis para mantener un directorio. Conectan bloques libres adyacentes cuando son posibles para poder proporcionar grandes bloques. El directorio puede o no puede implicar el uso de la memoria en bloques liberados para formar una lista vinculada. (La alternativa es un poco más de memoria compartida y amigable con las hojas, e implica asignar memoria específicamente para el directorio). MALLOC y LIBRES tienen poco si la capacidad de hacer cumplir el acceso a bloques individuales incluso cuando se compila el código especial y opcional de depuración. el programa.


1. El hecho de que muy pocas implementaciones de libre () intento de devolver la memoria al sistema no se deben en absoluto a los implementadores que se aflojan.

interactuando con el kernel es mucho más lento que Simplemente ejecutando el código de la biblioteca, y el beneficio sería pequeño. La mayoría de los programas tienen una huella de memoria de estado estable o en estado, por lo que el tiempo dedicado al analizar el montón que busca la memoria retornable se desperdiciaría completamente. Otras razones incluyen el hecho de que la fragmentación interna hace que existan bloques alineados por la página, y es probable que la devolución de un bloque se bloquee a ambos lados. Finalmente, es probable que los pocos programas que devuelven grandes cantidades de memoria.

Generalmente libre () no devuelve la memoria física a OS, todavía están asignados en la memoria virtual de su proceso.Si asigna un gran trozo de memoria, LIBC puede asignarlo por MMAP ();Luego, si lo libero, LIBC puede liberar la memoria a OS por MUNMAP (), en este caso, la parte superior mostrará que su uso de memoria se reduce.

Por lo tanto, si no desea liberar la memoria a SO explícitamente, puede usar MMAP () / MUNMAP ().

Cuando usted free() memoria, se devuelve al grupo de memoria de la biblioteca C estándar y no al sistema operativo.En la visión del sistema operativo, tal como lo ves a través top, el proceso todavía está "usando" esta memoria.Dentro del proceso, la biblioteca C ha tenido en cuenta la memoria y podría devolver el mismo puntero desde malloc() en el futuro.

Lo explicaré un poco más con un comienzo diferente:

Durante sus llamadas a malloc, la implementación de la biblioteca estándar puede determinar que el proceso no tiene suficiente memoria asignada por parte del sistema operativo.En ese momento, la biblioteca realizará una llamada al sistema para recibir más memoria del sistema operativo para el proceso (por ejemplo, sbrk() o VirtualAlloc() llamadas al sistema en Unix o Windows, respectivamente).

Después de que la biblioteca solicita memoria adicional del sistema operativo, agrega esta memoria a su estructura de memoria disponible para regresar. malloc.Llamadas posteriores a malloc utilizará esta memoria hasta que se agote.Luego, la biblioteca le pide al sistema operativo aún más memoria.

Cuando usted free memoria, la biblioteca generalmente no devuelve la memoria al sistema operativo.Hay muchas razones para esto.Una razón es que el autor de la biblioteca creía que llamarías malloc de nuevo.Si no llamas malloc Nuevamente, su programa probablemente terminará pronto.En cualquier caso, no hay mucha ventaja en devolver la memoria al sistema operativo.

Otra razón por la que es posible que la biblioteca no devuelva la memoria al sistema operativo es que la memoria del sistema operativo está asignada en rangos grandes y contiguos.Solo se puede devolver cuando un rango contiguo completo ya no esté en uso.El patrón de llamada malloc y free Es posible que no borre todo el rango de uso.

Dos problemas:

  • En make_cache_db(), la línea

    for (int i=0; i = n; i++)
    

    probablemente debería leer

    for (int i=0; i<n; i++)
    

    De lo contrario, solo asignarás una única cache_db_s nodo.

  • La forma en que estás asignando cache_db en make_cache_db() parece tener errores.Parece que su intención es devolver un puntero al primer elemento de la lista vinculada;pero porque estás reasignando cache_db En cada iteración del bucle, terminarás devolviendo un puntero al último elemento de la lista.

    Si luego libera la lista usando free_cache_db(), esto hará que pierda memoria.Por el momento, sin embargo, este problema está enmascarado por el error descrito en el punto anterior, que hace que usted asigne listas de solo longitud 1.

Independientemente de estos errores, el punto planteado por aix es muy válido:La biblioteca en tiempo de ejecución no necesita devolver todos free()d memoria al sistema operativo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top