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

c, free, realloc

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.

Problem

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

Original source