Search code examples
cmemorymallocallocation

Can I be sure that reallocating less memory will always find enough of it?


Let's say I have just malloced x bytes of memory, after doing something with them I want to realloc y < x bytes. Can I make that and yet be sure that my realloc will find enough memory? Example,

int *p = malloc(10);
if (p != NULL) {
    // Do something with `p`.
    int *p_ = realloc(p, 5);
    // Keep doing something else.
}

Should I make sure p_ isn't NULL even though I have reallocated less memory than the original one? I think *alloc functions return NULL when the requested memory exceeds the available one, is the previous code safe to use?


Solution

  • Can I be sure that reallocating less memory will always find enough of it?
    Can I make that and yet be sure that my realloc will find enough memory?

    No, realloc(p, 5); may fail and return NULL.


    Should I make sure p_ isn't NULL even though I have reallocated less memory than the original one?

    Yes, code, when down-sizing and return is NULL, could continue with the old value pointer - it is still valid.

    int *p_ = realloc(p, 5); 
    if (p_) {
      p = p_;
    } else /* if new_size <= old_size and new_size > 0 */ {
      ; // Simply continue with the old `p`, it is still good.
    }
    // Do something with `p`.
    …
    free(p);
    

    Note: this else path is, in general, hard to test.


    I think *alloc functions return NULL when the requested memory exceeds the available one, is the previous code safe to use?

    Do not assume. realloc() may return NULL if the new size is larger, the same or smaller than before.


    Design consideration:

    Returning NULL on realloc() when the size is reduced is plausible when 1) the number of memory handles is met (a system may only allow so many allocations) and calloc() could temporally need another one. 2) The new size is 0. The details of return value on *alloc(0) have a history and are a bit contentious and not further discussed here.

    In any case, as long as the new size is more than zero, a return of NULL implies some resource is at the end. Occam's razor suggest code proceed to the same error handling as when calloc() returns NULL due to a size growth.