Search code examples
cpointersdynamic-memory-allocationrealloc

Can I reuse a pointer after reallocating memory it points to?


I'm new to C. I knew that when I use realloc(), the pointer is deactivated as the new block of memory may be in another address (is it set to null?). But a pointer just stores the value of an address. So can I reuse that pointer to store another address after that? Moreover, can I do this:

ptr= realloc(ptr, newsize);

Solution

  • Yes, you can do that. It's nothing inherently wrong with it. However, it can make it impossible to recover from a failed allocation. If you're planning to exit the program if the allocation fails, it (usually) does not matter.

    So this is perfectly fine:

    ptr = realloc(ptr, newsize);
    if(!ptr) exit(EXIT_FAILURE);
    

    And so is this:

    tmpptr = realloc(ptr, newsize);
    if(!tmpptr) puts("Allocation failed. Continuing anyway.");
    else ptr = tmpptr; 
    

    Note: It can be argued if it's ok to exit with a memory leak. In most cases, that does not matter, since the operating system will usually clean everything up upon exit. So be aware that in the first example, you will exit with a memory leak.

    So if a memory leak does matter to you, even if you're exiting on failure, you can do something like this:

    tmpptr = realloc(ptr, newsize);
    if(!tmpptr) {
        free(ptr);
        exit(EXIT_FAILURE);
    } else {
        ptr = tmpptr; 
    }
    

    However, do notice that this would only solve the problem for the ptr pointer. If you have a program of any complexity above simple school assignments, chances are pretty high that you have a few other allocations already going on. Keeping track of all that is possible, but far from trivial. Consider this very minimalistic example:

    void foo() {
        void *ptr1 = malloc(SIZE);
        if(!ptr1) exit(EXIT_FAILURE);
        bar();
        free(ptr1);
    }
    
    void bar() {
        void *ptr2 = malloc(SIZE);         
        if(!ptr2) {
            // Here we should call free on ptr1 to avoid memory leaks, but how?
            exit(EXIT_FAILURE);
        }
        // Do work
        free(ptr2);
    }
    

    Of course, you could easily rewrite it:

    void foo() {
        void *ptr1 = malloc(SIZE);
        if(!ptr1) exit(EXIT_FAILURE);
        if(!bar()) exit(EXIT_FAILURE);
        free(ptr1);
    }
    
    int bar() {
        void *ptr2 = malloc(SIZE);         
        if(!ptr2) return 0;
        // Do work
        free(ptr2);
        return 1;
    }
    

    In this case, it was easy, but keep in mind that this example is VERY trivial.

    I would not bother unless I have a very good reason to care. It makes the code messy and is completely unnecessary on modern operating systems. Unless I'm writing code for an environment where it does matter, I would only care if I'm writing a function where I want it to be up to the caller to exit or not.

    The bottom line here is that making sure that all allocated resources are freed by the program on exit can be a complete nightmare. And unless you have the need for it and are willing to spend quite a lot of time getting it right, then don't bother.

    In practice, dealing with this would require you to take this into account for almost all aspects of the design. And that's very rarely a good tradeoff.

    Related question: dangers of _exit() - memory leak?