Regarding void *realloc(void *ptr, size_t size)
, the C standard says in C 2018 7.22.3.5 paragraphs 2 and 3:
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
. The contents of the new object shall be the same as that of the old object prior to deallocation, up to the lesser of the new and old sizes. Any bytes in the new object beyond the size of the old object have indeterminate values.
If ptr
is a null pointer, the realloc
function behaves like the malloc
function for the specified size. Otherwise, if ptr
does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to the free
or realloc
function, the behavior is undefined. If size
is nonzero and memory for the new object is not allocated, the old object is not deallocated. If size
is zero and memory for the new object is not allocated, it is implementation-defined whether the old object is deallocated. If the old object is not deallocated, its value shall be unchanged.
What this means when you ask to reduce the size of a previously allocated object is:
The returned pointer might or might not be the same as the original pointer. (See discussion below.)
The C standard permits the portion of memory that is released to be reused for other allocations. Whether or not it is reused is up to the C implementation.
Whether the values in the released portion of memory are immediately overwritten or not is not specified by the C standard. Certainly the user of realloc
may not rely on any behavior regarding that memory.
Discussion
When a memory allocation is reduced, it certainly seems “easy” for the memory allocation routines to simply return the same pointer while remembering that the released memory is free. However, memory allocation systems are fairly complex, so other factors may be involved. For example, hypothetically:
To support many small allocations without much overhead, a memory allocation system might create a pool of memory for one-to-four byte allocations, another pool for five-to-eight, another pool for eight-to-16, and a general pool for larger sizes. For the larger sizes, it might remember each allocation individually, customizing its size and managing them all with various data structures. For the smaller sizes, it might keep little more than a bitmap for each, with each bit indicating whether or not its corresponding four-byte (or eight or 16) region is allocated. In such a system, if you release eight bytes of a 16-byte allocation, the memory allocation software might move the data to something in the eight-byte pool.
In any memory allocation system, if you release just a few bytes at the end of an allocation, it might not be enough bytes to take advantage of—the data structures required to track the few bytes you released might be bigger than the few bytes. So it is not worthwhile to make them available for reuse. The memory allocation system just keeps them with the block, although it may remember the data in the block is actually a bit smaller than the space reserved for it.