Search code examples
cpointersmemory-leaksdynamic-memory-allocationrealloc

Safer way to realloc


I am implementing a function to safely realloc a structure in order not to lost the information if any allocation error occurs, something like this:

int foo (someStruct_t *ptr, int size)
{
    someStruct_t *tmp_ptr;

    tmp_ptr = realloc(ptr, size);

    if (tmp_ptr == NULL)
        return -1;

    ptr = tmp_ptr;

    return 0;
}

My doubt resides in the following: Am I not duplicating the allocated memory for the structure everytime I run this function? In my line of thought I should free one of the pointers before exiting, correct?


Solution

  • The primary and major problem here is, after a call to foo(), in the caller, the passed argument for ptr will not be changed, as it itself is passed by value.

    You need to pass a pointer to the pointer which you want to be reallocated, in case you don't want to return the new pointer.


    That said, there is no "duplication" of memory here.

    • From realloc() point of view

      realloc(), if successful, returns the pointer to the new memory and handles the job of de-allocating the older one. You don't need to worry about any duplication or memory leaks.

      Quoting C11, chapter §7.22.3.5 (emphasis mine)

      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. [....]

      [....] If memory for the new object cannot be allocated, the old object is not deallocated and its value is unchanged.

    • From the assignment point of view

      A statement like ptr = tmp_ptr; does not duplicate the memory or memory contents the pointer points to, it is just having two copies of the same pointer. For example, You can pass either of them to free().

    So, bottom line, to answer the "question" in the question,

    In my line of thought I should free one of the pointers before exiting, correct?

    No, you should not. You need to have the newly allocated pointer to be useful in the caller, free()-in it inside the called functions makes the whole function pointless. You should free the pointer from the caller, though.