Search code examples
cmemoryrealloc

Why does a pointer have to be assigned for realloc to work without altering the first value in the memory block?


int *ptr;
...
realloc(ptr,++count*sizeof(int));
      or
ptr=realloc(ptr,++count*sizeof(int));

I noticed if I use option number one more than once, the value of the first memory address (which ptr points to), becomes undefined (although all other values in the memory block are fine and can be accessed by subscripting ptr).

However, I assumed that all realloc does is either shrink or increase the size of a memory block, and ptr will still point to the same memory block and none of its values will change. So if I use option number one, why does the first address in the memory block end up having an unexpected value, because doesn't ptr still point to the same address?

EDIT: I did remember to allocate memory to ptr, just didn't think it work mentioning.


Solution

  • The pointer returned by realloc may or may not point to the same address as the pointer you passed to it.

    Typically if you're expanding a memory block, there may not be enough room to expand it in place. In that case realloc allocates a new chunk of memory, copies the contents of the old object to the newly allocated chunk, and returns a pointer to the new chunk. If you don't assign the result to a pointer object, you've just lost it (the old chunk is deallocated, and you don't know where the new one is).

    realloc can even return a pointer to a newly allocated block of memory if it shrinks the allocated block. There might be good reasons to allocate smaller chunks from a different region of memory.

    You also need to be aware that realloc can fail. If it does, it returns a null pointer -- and the old pointer is still valid (just not pointing to a block of memory of the size you wanted). (In principle, realloc can fail even if the new size is smaller than the old one.) So unless your response to an allocation failure is to abort the program, or at least the part of it that uses the pointer, you should assign the result to a different pointer object:

    int *ptr = ...;
    int *new_ptr;
    new_ptr = realloc(ptr, new_size);
    if (new_ptr == NULL) {
        /* ptr still points to the old block of memory; you can try something else */
    }
    else {
        ptr = new_ptr; /* Now you can forget the old pointer value */
    }
    

    If realloc succeeds, the pointer value it returns is valid, and the pointer you passed to it is invalid.

    If realloc fails, it returns a null pointer, and the pointer you passed to it is still valid.