Can malloc_trim () free memory from the middle of the heap?

I got confused about the malloc_trim behavior implemented in glibc.

man malloc_trim
[...]
malloc_trim - release free memory from the top of the heap
[...]
This function cannot release free memory located at places other than the top of the heap.

When I now look at the source malloc_trim()(in malloc / malloc.c), I see what it calls mtrim(), which it uses madvise(x, MADV_DONTNEED)to free memory back to the operating system.

So I'm wondering if the man page is incorrect or misinterpreted the source in the malloc / malloc.c file.

Can malloc_trim()free memory from the middle of the heap?

+1
source share
2 answers

... using madvise (x, MADV_DONTNEED) to get memory back to the operating system.

madvise(x, MADV_DONTNEED) . man madvise:

MADV_DONTNEED
               . ( ,                ,                , .)                ,                              (. mmap (2))                .

, madvise(x, MADV_DONTNEED) man malloc_trim:

, , .

+2

glibc madvise MADV_DONTNEED: http://code.metager.de/source/search?q=MADV_DONTNEED&path=%2Fgnu%2Fglibc%2Fmalloc%2F&project=gnu

 H A D  arena.c 643 __madvise ((char *) h + new_size, diff, MADV_DONTNEED);
 H A D  malloc.c    4535 __madvise (paligned_mem, size & ~psm1, MADV_DONTNEED);

https://sourceware.org/git/?p=glibc.git;a=commit;f=malloc/malloc.c;h=68631c8eb92ff38d9da1ae34f6aa048539b199cc 16 2007 ( glibc 2.9 ):

  • malloc/malloc.c(public_mTRIm):

mTRIm . (mTRIm): madvise , .

mTRIm ( mTRIm) . , , , MADV_DONTNEED:

           /* See whether the chunk contains at least one unused page.  */
           char *paligned_mem = (char *) (((uintptr_t) p
                                           + sizeof (struct malloc_chunk)
                                           + psm1) & ~psm1);

           assert ((char *) chunk2mem (p) + 4 * SIZE_SZ <= paligned_mem);
           assert ((char *) p + size > paligned_mem);

           /* This is the size we could potentially free.  */
           size -= paligned_mem - (char *) p;

           if (size > psm1)
               madvise (paligned_mem, size & ~psm1, MADV_DONTNEED);

malloc_trim : https://github.com/mkerrisk/man-pages/blob/master/man3/malloc_trim.3, kerrisk 2012 : https://github.com/mkerrisk/man-pages/commit/a15b0e60b297e29c825b7417582a33e6ca26bf65

grep glibc git, glibc man-, man- malloc_trim . glibc malloc : https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c

Additional functions:
 malloc_trim(size_t pad);
 609 /*
 610   malloc_trim(size_t pad);
 611 
 612   If possible, gives memory back to the system (via negative
 613   arguments to sbrk) if there is unused memory at the `high' end of
 614   the malloc pool. You can call this after freeing large blocks of
 615   memory to potentially reduce the system-level memory requirements
 616   of a program. However, it cannot guarantee to reduce memory. Under
 617   some allocation patterns, some large free blocks of memory will be
 618   locked between two used chunks, so they cannot be given back to
 619   the system.
 620 
 621   The `pad' argument to malloc_trim represents the amount of free
 622   trailing space to leave untrimmed. If this argument is zero,
 623   only the minimum amount of memory to maintain internal data
 624   structures will be left (one page or less). Non-zero arguments
 625   can be supplied to maintain enough trailing space to service
 626   future expected allocations without having to re-obtain memory
 627   from the system.
 628 
 629   Malloc_trim returns 1 if it actually released any memory, else 0.
 630   On systems that do not support "negative sbrks", it will always
 631   return 0.
 632 */
 633 int      __malloc_trim(size_t);
 634 

, malloc/malloc.c( malloc_trim commend 2007 ) man-pages. 2012 , glibc. glibc M_TRIM_THRESHOLD 128 KB: https://www.gnu.org/software/libc/manual/html_node/Malloc-Tunable-Parameters.html#Malloc-Tunable-Parameters malloc_trim https://www.gnu.org/software/libc/manual/html_node/Summary-of-Malloc.html#Summary-of-Malloc ( memusage/memusagestat/libmemusage.so).

Drepper glibc, https://sourceware.org/ml/libc-help/2015-02/msg00022.html " malloc_trim()", . ( , https://sourceware.org/ml/libc-help/2015-05/msg00007.html https://sourceware.org/ml/libc-help/2015-05/msg00008.html)

malloc_trim C (test_malloc_trim.c) strace/ltrace:

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

int main()
{
    int *m1,*m2,*m3,*m4;
    printf("%s\n","Test started");
    m1=(int*)malloc(20000);
    m2=(int*)malloc(40000);
    m3=(int*)malloc(80000);
    m4=(int*)malloc(10000);
    printf("1:%p 2:%p 3:%p 4:%p\n", m1, m2, m3, m4);
    free(m2);
    malloc_trim(0); // 20000, 2000000
    sleep(1);
    free(m1);
    free(m3);
    free(m4);
    // malloc_stats(); malloc_info(0, stdout);
    return 0;
}

gcc test_malloc_trim.c -o test_malloc_trim, strace ./test_malloc_trim

write(1, "Test started\n", 13Test started
)          = 13
brk(0)                                  = 0xcca000
brk(0xcef000)                           = 0xcef000
write(1, "1:0xcca010 2:0xccee40 3:0xcd8a90"..., 441:0xcca010 2:0xccee40 3:0xcd8a90 4:0xcec320
) = 44
madvise(0xccf000, 36864, MADV_DONTNEED) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, 0x7ffffafbfff0)       = 0
brk(0xceb000)                           = 0xceb000

, malloc_trim(0) madvise MADV_DONTNEED 9 , 40008 .

0

Source: https://habr.com/ru/post/1656120/


All Articles