Search code examples
cmallocmmapbrk

Will malloc round up to the nearest page size?


I'm not sure if I'm asking a noob question here, but here I go. I also searched a lot for a similar question, but I got nothing.

So, I know how mmap and brk work and that, regardless of the length you enter, it will round it up to the nearest page boundary. I also know malloc uses brk/sbrk or mmap (At least on Linux/Unix systems) but this raises the question: does malloc also round up to the nearest page size? For me, a page size is 4096 bytes, so if I want to allocate 16 bytes with malloc, 4096 bytes is... a lot more than I asked for.


Solution

  • #include <stdio.h>
    #include <stdlib.h>
    #include <inttypes.h>
    #include <unistd.h>
    
    
    int main(void) {
        void *a = malloc(1);
        void *b = malloc(1);
        uintptr_t ua = (uintptr_t)a;
        uintptr_t ub = (uintptr_t)b;
        size_t page_size = getpagesize();
    
        printf("page size: %zu\n", page_size);
        printf("difference: %zd\n", (ssize_t)(ub - ua));
        printf("offsets from start of page: %zu, %zu\n",
            (size_t)ua % page_size, (size_t)ub % page_size);
    }
    

    prints

    page_size: 4096
    difference: 32
    offsets from start of page: 672, 704
    

    So clearly it is not rounded to page size in this case, which proves that it is not always rounded to page size.


    It will hit mmap if you change allocation to some arbitrary large size. For example:

    void *a = malloc(10000001);
    void *b = malloc(10000003);
    

    and I get:

    page size: 4096
    difference: -10002432
    offsets from start of page: 16, 16
    

    And clearly the starting address is still not page aligned; the bookkeeping must be stored below the pointer and the pointer needs to be sufficiently aligned for the largest alignment generally needed - you can reason this with free - if free is just given a pointer but it needs to figure out the size of the allocation, where could it look for it, and only two choices are feasible: in a separate data structure that lists all base pointers and their allocation sizes, or at some offset below the current pointer. And only one of them is sane.