¿Free () desasigna la memoria de un proceso?

8

Estoy ejecutando un programa C en el kernel de Linux 2.6.16. No creo que haya pérdidas de memoria en mi programa, sin embargo, el consumo de memoria para el programa permanece estable después de ciertas operaciones y no disminuye. Uso el comando 'ps v' para monitorear el valor RSS de mi programa.

La herramienta valgrind massif muestra que mmap asigna una gran parte del montón en mi proceso. Pero de acuerdo con el código, esas asignaciones deberían haberse liberado después de que se realicen las operaciones. ¿Es porque la memoria liberada todavía está asignada y / o todavía contribuye al valor RSS del proceso?

Cualquier idea será muy apreciada!

A continuación se muestra el recorte del informe valgrind macizo. Tenga en cuenta que he activado la opción --pages-as-heap para la herramienta de macizo para medir todas las memorias utilizadas por el programa.

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 85 701,483,989,262      173,576,192      173,576,192             0            0
 86 704,352,949,469      173,367,296      173,367,296             0            0
 87 707,582,275,643      173,367,296      173,367,296             0            0
 88 710,536,145,814      173,367,296      173,367,296             0            0
100.00% (173,367,296B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc.
->53.40% (92,581,888B) 0x649248B: mmap (in /lib64/tls/libc.so.6)
| ->41.13% (71,303,168B) 0x6446D85: _int_malloc (in /lib64/tls/libc.so.6)
| | ->39.31% (68,157,440B) 0x6448D62: calloc (in /lib64/tls/libc.so.6)
......[my own functions are omitted]
->35.28% (61,157,376B) 0x400F51B: mmap (in /lib64/ld-2.3.3.so)
| ->28.81% (49,954,816B) 0x4004CE8: _dl_map_object_from_fd (in /lib64/ld-2.3.3.so)
| | ->28.81% (49,954,816B) 0x400636B: _dl_map_object (in /lib64/ld-2.3.3.so)
| |   ->18.89% (32,755,712B) 0x400AB42: openaux (in /lib64/ld-2.3.3.so)
| |   | ->18.89% (32,755,712B) 0x400AF7C: _dl_catch_error (in /lib64/ld-2.3.3.so)
| |   |   ->18.89% (32,755,712B) 0x4009FCF: _dl_map_object_deps (in /lib64/ld-2.3.3.so)
| |   |     ->18.89% (32,755,712B) 0x40021FD: dl_main (in /lib64/ld-2.3.3.so)
| |   |       ->18.89% (32,755,712B) 0x400E7F6: _dl_sysdep_start (in /lib64/ld-2.3.3.so)
| |   |         ->18.89% (32,755,712B) 0x4001477: _dl_start (in /lib64/ld-2.3.3.so)
| |   |           ->18.89% (32,755,712B) 0x4000CF6: ??? (in /lib64/ld-2.3.3.so)
| |   |             ->18.89% (32,755,712B) 0x0: ???
| |   |               ->18.89% (32,755,712B) 0x7FF0003D5: ???
| |   |                 ->18.89% (32,755,712B) 0x7FF0003E4: ???
| |   |
......
michelle
fuente
¿Por qué no estás usando munmap? munmap (2)
Mikel
¿Estás usando bibliotecas compartidas? ¿Puede proporcionar partes relevantes de la producción desde valgrindy también /proc/<PID>/maps?
Mikel
No usamos munmap ya que glibc malloc y free tienen las implementaciones. Sí, se utilizan bibliotecas compartidas. ¿Por que importa? Las partes relevantes del informe valgrind se agregan a la pregunta principal.
michelle
Vea la desasignación de memoria de UNIX vs Windows
Gilles 'SO- deja de ser malvado'
@michelle Pensé que querías decir que estabas llamando mmap. Pero ahora creo que entiendo: ¿estás llamando malloc/ callocy está llamando mmap?
Mikel

Respuestas:

5

La función de biblioteca C free()puede, pero no es necesario, devolver la memoria al núcleo.

Algunas implementaciones de malloc()mover el límite entre el "montón" y el espacio de direcciones no utilizado (el "corte del sistema") a través de la sbrk()llamada al sistema, luego reparten piezas más pequeñas de esas grandes asignaciones. Sin desasignar cada pieza más pequeña, free()realmente no puedo devolver la memoria al sistema operativo.

Esa misma razón se aplica a las malloc()implementaciones que no usan sbrk(2), pero tal vez usan mmap("/dev/zero")o algo así. No puedo encontrar una referencia, pero parece recordar que uno u otro de los BSD usa mmap()esa manera para obtener páginas de memoria. Sin embargo, free()no se puede devolver una página al sistema operativo a menos que el programa desasigne todas las subasignaciones.

Algunas malloc()implementaciones devuelven memoria al sistema: ChorusOS (?) Aparentemente lo hizo. No está claro si movió el sistema roto, o las munmap()'edpáginas.

Aquí hay un documento sobre un asignador de memoria que mejora el rendimiento al "renunciar agresivamente a páginas gratuitas para el administrador de memoria virtual". Presentación de diapositivas para una charla sobre el asignador.

Bruce Ediger
fuente
Entiendo que free () no devuelve recuerdos al sistema operativo. ¿Pero free () anula la asignación de la memoria o la memoria queda por asignar por el asignador de memoria glibc?
michelle
"free () no puede devolver una página al sistema operativo a menos que cada subasignación sea desasignada por el programa". Realmente no entiendo esto. ¿Podría explicar 'subasignación'?
michelle
1
@michelle: suponga un tamaño de página de 4192 bytes. Un programa llama a malloc (4186) y luego a malloc (8). El programa ha asignado toda una página. El programa llama a free () en la asignación de 4186 bytes. free () no puede desasignar la página porque la asignación de 8 bytes no ha sido free () 'ed.
Bruce Ediger
Eso tiene sentido. Gracias Bruce Entonces, supongo que cuando la página todavía está asignada, todos los datos en ella aún se tienen en cuenta por la medición valgrind, aunque algunos ya están liberados. ¿Correcto?
michelle