8

I am trying to reallocate memory using realloc in the below program and checking after realloc initial memory which i was reacted using malloc(i = (int*)malloc(5 * sizeof(int))) still exist or not, using below program i am able to access the data after realoc i have checked by using another pointer (i.e *m). is this proper behavior ? or memory should be free once realloc called?

    #include <stdio.h>
    #include <stdlib.h>

    int main()
    {
       int *i,*jn, *m;
       i = (int*)malloc(5 * sizeof(int));
       int j,k=10;

      for(j=0 ;j<5; j++)
      {
         i[j] = j;
         printf("%d \n",i[j]);
      }

      for(j=0 ;j<5; j++)
      {
        printf("%p\n",i++);
      }

      jn = (int *)calloc(5, sizeof(*i));

      for(j=0 ;j<5; j++)
      {
         printf("%p\n",jn++);
      }

       i = i-5;
       m = i;

      printf("m = %p  %d\n",(m+1), *(m+1));

      i =(int *)realloc(i,8*sizeof(int));

      for(j=0 ;j<8; j++)
      {

         printf("%d\n",i[j]);
      }

      for(j=0 ;j<8; j++)
      {

        printf("%p\n",i++);
      }
      printf("m = %p  %d\n",(m+1), *(m+1));

      return 0;
}
1
  • 1
    I would consider this a question of ownership rather than a specific action. If realloc succeeds, it will take ownership of the incoming memory (either manipulating it or freeing it) and return a pointer that can be used ("owned") by the calling function. If realloc fails (returns NULL), your function retains ownership of the original memory and should free it when it's done with it. Commented Sep 28, 2017 at 5:12

2 Answers 2

22

Firstly, realloc might decide to

  1. Allocate a new memory block, copy data, and free the original one, or

  2. Simply expand/contract the original block "in place" without allocating the new one.

Which approach it will choose depends on the implementation and various other external factors. It might follow the first approach. Or it might follow the second approach. You can easily figure out which approach it followed by comparing the values of pointers i and m after realloc.

Secondly, if realloc decided to follow the first approach (i.e. allocate a new memory block), then the old block is indeed freed by realloc. In that case trying to access the original memory location leads to undefined behavior.

If realloc decided to follow the second approach (i.e. expand or shrink the original memory block "in place"), then m and i will keep pointing to the same location. In that case there's no surprise in seeing the same data through m.

P.S. This means that the behavior of your code is either trivial or undefined. It can't really be used to analyze whether the behavior is "proper". What did your expect to happen if the memory was indeed freed?

Sign up to request clarification or add additional context in comments.

4 Comments

The C11 standard says (§7.22.3.5): 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. … The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object could not be allocated. C99 says the same. C90 wasn't explicit about the old memory being deallocated, unlike C99 and C11 which are.
From above code i got below output.( 0 1 2 3 4 0x9a40008 0x9a4000c 0x9a40010 0x9a40014 0x9a40018 0x9a40020 0x9a40024 0x9a40028 0x9a4002c 0x9a40030 m = 0x9a4000c 1 0 1 2 3 4 0 0 0 0x9a40038 0x9a4003c 0x9a40040 0x9a40044 0x9a40048 0x9a4004c 0x9a40050 0x9a40054 m = 0x9a4000c 1 )with this output if realloc free the old memory how come *m pointer able to access the old memory location and the data which is present in old memory location
@SumitNaik Accessing freed memory results in undefined behavior, which can manifest itself in an infinitude of different ways. It just as well might appear to "see" the old values. The real question here is why you even care. Even if you are able to somehow access freed memory, the residual data "stored" there is garbage. It does not mean anything.
@JonathanLeffler There's probably some conceptual value in describing realloc'c behavior as always freeing the old memory (at least internally), but this question appears to concern itself mostly with the status of that memory after realloc finished working. To the outside observer (and within the context of this question) it probably does not matter whether the memory block was freed and then allocated at the same location or was simply expanded/contracted "in place".
10

realloc is equivalent to:

void *
realloc(void *old, size_t newsz)
{
    size_t old_sz = internal_function_that_finds_old_size(old);
    void *new = malloc(newsz);
    if (new == NULL)
        return NULL;
    memcpy(new, old, oldsz);
    free(old);
    return new;
}

realloc can do something more efficient including not changing the pointer and just making the size allocated bigger, it can use kernel facilities to map the memory somewhere else to avoid the copy, etc. But in general realloc should be treated as doing exactly what I wrote above because that is the worst case behavior.

Now, when it comes to your program. You're touching memory through invalid pointers, anything can happen. m stops being a valid pointer after the call to realloc. It doesn't mean that anyone will stop you from using it, it just means that if you do use it your program is no longer guaranteed to do anything sensible.

3 Comments

Argh the new highlighted in blue!
@MatteoItalia heh. I guess syntax highlighting on SO believes in the C/C++ myth.
@Art So realloc alwasys frees old pointer if process is successful, right? What if I don't want to free old memory but I want to have a reallocated (for ex. bigger) memory which is copy of the old one? Should manually call malloc and then copy bytes?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.