Free () démappe-t-il la mémoire d'un processus?


8

J'exécute un programme C sur le noyau Linux 2.6.16. Je ne pense pas qu'il y ait des fuites de mémoire dans mon programme mais la consommation de mémoire pour le programme reste stable après certaines opérations et ne diminue pas. J'utilise la commande «ps v» pour surveiller la valeur RSS de mon programme.

L'outil Valgrind massif montre qu'une grande partie du tas est allouée par mmap dans mon processus. Mais selon le code, ces allocations auraient dû être libérées une fois les opérations terminées. Est-ce parce que la mémoire libérée est toujours mappée et / ou contribue toujours à la valeur RSS du processus?

Tout aperçu sera très apprécié!

Ci-dessous, un extrait du rapport sur le massif du Valgrind. Remarque J'ai activé l'option --pages-as-heap pour que l'outil massif mesure toutes les mémoires utilisées par le programme.

--------------------------------------------------------------------------------
  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: ???
| |   |
......

Pourquoi n'utilisez-vous pas munmap? munmap (2)
Mikel

Utilisez-vous des bibliothèques partagées? Pouvez-vous fournir des parties pertinentes de la sortie de valgrindainsi que /proc/<PID>/maps?
Mikel

Nous n'utilisons pas munmap puisque glibc malloc et free ont les implémentations. Oui, des bibliothèques partagées sont utilisées. Pourquoi est-ce important? Les parties pertinentes du rapport valgrind sont ajoutées à la question principale.
michelle


@michelle Je pensais que tu voulais dire que tu appelais mmap. Mais maintenant je pense que je comprends: vous appelez malloc/ calloc, et ça appelle mmap?
Mikel du

Réponses:


5

La fonction de bibliothèque C free()peut, mais n'est pas obligée, renvoyer de la mémoire au noyau.

Certaines implémentations de malloc()déplacer la frontière entre "tas" et l'espace d'adressage autrement inutilisé (la "rupture du système") via l' sbrk()appel système, puis distribuent des morceaux plus petits de ces grandes allocations. Sans que chaque petit morceau soit désalloué, free()il ne peut pas vraiment retourner la mémoire au système d'exploitation.

Cette même raison s'applique aux malloc()implémentations qui n'utilisent pas sbrk(2), mais peut-être utiliser mmap("/dev/zero")ou quelque chose .. Je ne trouve pas de référence, mais il me semble que l'un ou l'autre des BSD a utilisé de mmap()cette façon pour obtenir des pages de mémoire. Néanmoins, free()ne peut pas retourner une page au système d'exploitation à moins que chaque sous-allocation soit désallouée par le programme.

Certaines malloc()implémentations renvoient de la mémoire au système: ChorusOS (?) L'a apparemment fait. Il n'est pas clair s'il a déplacé la rupture du système ou les munmap()'edpages.

Voici un article sur un allocateur de mémoire qui améliore les performances en «abandonnant de manière agressive des pages libres au gestionnaire de mémoire virtuelle». Diaporama pour une présentation de l'allocateur.


Je comprends que free () ne renvoie pas de souvenirs à OS. Mais free () démappe-t-il la mémoire ou la mémoire reste-t-elle à mapper par l'allocateur de mémoire glibc?
michelle

"free () ne peut pas retourner une page au système d'exploitation à moins que chaque sous-allocation ne soit désallouée par le programme." Je ne comprends pas vraiment cela. Pourriez-vous expliquer la «sous-allocation»?
michelle

1
@michelle: supposons une taille de page de 4192 octets. Un programme appelle malloc (4186) puis malloc (8). Le programme a alloué l'ensemble d'une page. Le programme appelle free () sur l'allocation de 4186 octets. free () ne peut pas démapper la page car l'allocation de 8 octets n'a pas été libérée ().
Bruce Ediger

Ça a du sens. Merci Bruce. Donc, je suppose que lorsque la page est toujours mappée, toutes les données qu'elle contient sont toujours prises en compte par la mesure de valgrind bien que certaines soient déjà libérées. Correct?
michelle
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.