Force free () à renvoyer la mémoire de malloc à l’OS

On dirait que même après avoir libéré toute la mémoire d’un processus Linux alloué par malloc (), la mémoire est toujours réservée au processus et n’est pas renvoyée au système d’exploitation.

L’exécution de l’outil Valgrind Massif par défaut ne révèle aucune fuite.

Exécuter valgrind avec –pages-as-heap = yes révèle ceci:

-> 13,77% (7 655 424 B) 0x35FEEEB069: brk (brk.c: 31)

-> 13,77% (7 655 424 B) 0x35FEEEB113: sbrk (sbrk.c: 53)

-> 13,77% (7 655 424 B) 0x35FEE82717: __default_morecore (morecore.c: 48)

-> 13,77% (7 655 424 B) 0x35FEE7DCCB: _int_malloc (malloc.c: 2455)

-> 13,77% (7 655 424 B) 0x35FEE7F4F1: malloc (malloc.c: 2862)

Ainsi, même si la mémoire a déjà été libérée par free (), il semble que malloc ait appelé brk / sbrk et ne le renvoie pas au système d’exploitation.

comment puis-je forcer free () à appeler sbrk () immédiatement et à restituer toute la mémoire au système d’exploitation?

Je travaille sur une plate-forme très bas de gamme où chaque MB compte.

Merci d’avance.

Le seul moyen fiable et portable de récupérer de la mémoire dans le système d’exploitation consiste à quitter le processus et à le redémarrer à nouveau, en restaurant tout état dont vous avez besoin pour continuer.

Bien sûr, écrire votre propre implémentation malloc / free en utilisant brk / sbrk selon vos besoins est l’autre option.

Avec glibc, malloc essaie d’appeler la fonction malloc_sortingm . Il n’est pas bien documenté et des modifications y ont été apscopes vers 2007 (glibc 2.9) – https://stackoverflow.com/a/42281428 .

Depuis 2007, cette fonction va: Itérer sur tous les domaines de la mémoire malloc (utilisés dans les applications multithread) en effectuant la consolidation sortingm et fastbin; et libérez toutes les pages alignées (4Ko) entièrement libérées.

https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1a34f6aa048539b199cc

Ulrich Drepper Sun, 16 décembre 2007 22:53:08 +0000 (22:53 +0000)

  • malloc / malloc.c (public_mTRIm): Parcourez toutes les arènes et appelez mTRIm pour toutes.

(mTRIm): En outre, parcourez tous les blocs libres et utilisez madvise pour libérer de la mémoire pour tous les blocs contenant au moins une page mémoire.

https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=malloc/malloc.c;h=c54c203cbf1f024e72493546221305b4fd5729b7;hp=1e716089a2b976d120c304ad75dd95c63737ad75;hb=68631c8eb92ff38d9da1ae34f6aa048539b199cc;hpb=52386be756e113f20502f181d780aecc38cbb66a

 + malloc_consolidate (av); ... + for (int i = 1; i < NBINS; ++i) ... + for (mchunkptr p = last (bin); p != bin; p = p->bk) + { ... + /* See whether the chunk contains at least one unused page. */ + char *paligned_mem = (char *) (((uintptr_t) p + + sizeof (struct malloc_chunk) + + psm1) & ~psm1); ... + /* This is the size we could potentially free. */ + size -= paligned_mem - (char *) p; + + if (size > psm1) + { ... + madvise (paligned_mem, size & ~psm1, MADV_DONTNEED); 

Donc, appeler malloc_sortingm libérera la quasi-totalité de la mémoire libérée dans le système d’exploitation. Seules les pages contenant des données non encore libérées seront conservées. Le système d’exploitation peut annuler l’affectation ou non de la page physique lorsque MADV_DONTNEED est utilisé et que Linux désaffecte l’unmap. Les pages madvised comptent toujours jusqu’à VSIZE (taille totale de la mémoire virtuelle du processus), mais consortingbuent généralement à réduire le RSS (quantité de mémoire physique utilisée par le processus).

Alternativement, vous pouvez essayer de basculer vers une autre bibliothèque malloc: tcmalloc (gperftools / google-perftools) ou jemalloc (facebook), qui ont tous deux des règles agressives pour restituer la mémoire libérée à l’OS (avec MADV_DONTNEED ou même MADV_FREE ).