cmemory-managementmallocfreebrk

Heap break will not change after free()?


Code:

int main() {
    printf("entering main. %p\n", sbrk(0));

    void* ptr = malloc(300 * 1024);
    memset(ptr, 0xBE, 300 * 1024);
    printf("Allocated memory. %p\n", sbrk(0));
    free(ptr);
    printf("Freed memory. %p\n", sbrk(0));

    void* ptr1 = malloc(300 * 1024);
    memset(ptr1, 0xBE, 300 * 1024);
    printf("Allocated memory. %p\n", sbrk(0));
    free(ptr1);
    printf("Freed memory. %p\n", sbrk(0));

    void* ptr2 = malloc(300 * 1024);
    memset(ptr2, 0xBE, 300 * 1024);
    printf("Allocated memory. %p\n", sbrk(0));
    free(ptr2);
    printf("Freed memory. %p\n", sbrk(0));

    printf("exiting main. %p\n", sbrk(0));
}

Output:

entering main. 0x2403000
Allocated memory. 0x2424000
Freed memory. 0x2424000
Allocated memory. 0x246f000
Freed memory. 0x246f000
Allocated memory. 0x246f000
Freed memory. 0x246f000
exiting main. 0x246f000

Strace snippet(excluded lib loads):

 0.000064 [00007fc92fa32f19] brk(NULL) = 0x2403000
 0.000033 [00007fc92fa2cd34] fstat(1</dev/pts/33>, {st_dev=makedev(0, 14), st_ino=36, st_mode=S_IFCHR|0620, st_nlink=1, st_uid=60141191, st_gid=5, st_blksize=1024, st_blocks=0, st_rdev=makedev(136, 33), st_atime=2022/08/11-11:19:36.874073993, st_mtime=2022/08/11-11:19:36.874073993, st_ctime=2022/08/11-10:34:22.874073993}) = 0
 0.000084 [00007fc92fa32f19] brk(0x2424000) = 0x2424000
 0.000026 [00007fc92fa2d3c0] write(1</dev/pts/33>, "entering main. 0x2403000\n", 25) = 25
 0.000040 [00007fc92fa377ba] mmap(NULL, 311296, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc92fead000
 0.000200 [00007fc92fa2d3c0] write(1</dev/pts/33>, "Allocated memory. 0x2424000\n", 28) = 28
 0.000034 [00007fc92fa37847] munmap(0x7fc92fead000, 311296) = 0
 0.000042 [00007fc92fa2d3c0] write(1</dev/pts/33>, "Freed memory. 0x2424000\n", 24) = 24
 0.000052 [00007fc92fa32f19] brk(0x246f000) = 0x246f000
 0.000200 [00007fc92fa2d3c0] write(1</dev/pts/33>, "Allocated memory. 0x246f000\n", 28) = 28
 0.000031 [00007fc92fa2d3c0] write(1</dev/pts/33>, "Freed memory. 0x246f000\n", 24) = 24
 0.000033 [00007fc92fa2d3c0] write(1</dev/pts/33>, "Allocated memory. 0x246f000\n", 28) = 28
 0.000043 [00007fc92fa2d3c0] write(1</dev/pts/33>, "Freed memory. 0x246f000\n", 24) = 24
 0.000030 [00007fc92fa2d3c0] write(1</dev/pts/33>, "exiting main. 0x246f000\n", 24) = 24
 0.000036 [00007fc92fa027c8] exit_group(0) = ?

As we can see the heap break is increased when the memory is allocated (strace shows first allocation done by mmap also freed by munmap and second allocation done by brk. and there is no third allocation.).

But I don't see heap break decreases when free() is called.

I would like to know the reason for this behavior. Is it like kernel not freeing memory in case of future allocation for the process?


Solution

  • If yes is there a way to forcefully release the heap once freed by any kernel setting?

    Not by using standard C. glibc you can use malloc_trim function.

    https://man7.org/linux/man-pages/man3/malloc_trim.3.html

    You can set the threshold using mallopt function.

    If you set mallopt(M_TRIM_THRESHOLD, 0) your program will release the memory to the system when you use free (not exactly - some memory will still be kept)