Search code examples
cfreerealloc

In C is it possible to shrink the allocated memory without moving it?


Is there a method/function that frees up memory without the possibility of moving it to a new pointer in c?

Thanks!


Solution

  • According to a strict interpretation of the C99 standard, any call to realloc(), including to reduce the size of an allocated block, may return a pointer different from the argument. In fact, according to a strict interpretation of the standard, you are not allowed to compare the old pointer with the new pointer, because passing the old pointer to realloc() renders all existing copies of it indeterminate.

    The realloc function deallocates the old object pointed to by ptr and returns a pointer to a new object that has the size specified by size. … (C99 7.20.3.4:2)


    However, the man page for realloc() on my system says:

    If there is not enough room to enlarge the memory allocation pointed to by ptr, realloc() creates a new allocation, copies as much of the old data pointed to by ptr as will fit to the new allocation, frees the old allocation, and returns a pointer to the allocated memory.

    This more or less implies that realloc() can only move data and return a new pointer when used to enlarge a block. This would suggest that on this platform, realloc() can be used to reduce the size of a block obtained from malloc() without risk of moving it.

    If I was to use realloc() to reduce the size of an allocated block without moving it, I would use the check below:

    uintptr_t save = old;
    void * new = realloc(old, …);
    assert (save == (uintptr_t) new);
    

    These precautions are not for nothing, see for instance Winner #2 in this informal undefined behavior competition.

    2021 EDIT: Years later, however, further efforts to re-interpret and evolve the definition of C as that of a high-level language mean that even of the above three lines are perfectly legal, even after executing them, you cannot use an old copy of old to access the block pointed by new, even though these pointers point to the same place. See the current paper about pointer provenance in C.