Search code examples
cdynamic-memory-allocationrealloc

Behavior of `realloc()` when the memory is shrunk


The man page of realloc() says:

The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size is larger than the old size, the added memory will not be initialized.

However, the man page doesn't say anything about what happens if the new size is less than the old size. For example, if I have the following code:

ptr = realloc(ptr, nsize); // Where nsize < the original size and ptr is of type void **

If the original size is size, does that mean ptr + nsize + 1 still contains allocated entries?

Any help is appreciated.


Solution

  • first you probably mean:

    void **ptr = malloc(nsize*2);
    

    then

    ptr = realloc(ptr, nsize);
    

    or the safe way:

    void **ptr2 = realloc(ptr, nsize);
    if (ptr2 != NULL)
    {
       ptr = ptr2;
    } // else failure
    

    because using realloc(ptr,nsize) to set the value of ptr is undefined behaviour and probably crashes.

    Now, the system reduces the memory size as stated in Can I assume that calling realloc with a smaller size will free the remainder?

    Now your question is:

    If the original size is size, does that mean ptr + nsize + 1 still contains allocated entries?

    you have no guarantee of that. This is undefined behaviour from ptr + nsize already (thanks Sourav).

    Why? this area doesn't belong to your program anymore.

    You could have bugs reading past the new smaller array, which would yield valid results if the old data was there, which is probable, true, but:

    • the system could keep the same memory location, but reuse this block immediately for other data
    • the system could move the new data to another memory location (so old ptr would be different from new ptr, hence the return value that some people ignore and it "works" until it crashes), in that case, what's behind is complete irrelevant data.

    If both conditions above don't happen, it's very likely that the data is unchanged. realloc won't going to set to 0 some memory that isn't supposed to be used. Some debug frameworks (which ones I don't remember) put a pattern when deallocating memory so if you stumble on this pattern in your program it's a clear indication that you're reading an unallocated/uninitialized memory, but it has overhead, so it's not done by default. You can "overload" the memory allocation functions to do that yourself too.

    Anyhow, make sure you're not reading past the new array, as what you'll find isn't guaranteed.