user3478972
user3478972

Reputation:

Why realloc() in C changes memory?

I thought that realloc() function reallocates the memory and doesn't change it. After debugging an assignment that I had to do I realized that realloc() changed some elements in the memory and created bugs.

So I wrote the following code:

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

int main() {
    int *a, *p;
    a = (int*)calloc(10, sizeof(int));
    for (int i = 0;i < 10; i++)
        a[i] = i;
    for (int i = 0; i < 10; i++)
        printf("%d ", a[i]);
    printf("\n");
    p = realloc(a, 20);
    p[10] = 10;
    for (int i = 0; i < 11; i++)
        printf("%d ", p[i]);
    printf("\n");
    for (int i = 0; i < 10; i++)
        printf("%d ", a[i]);

    return 0;
}

and I got the following output

enter image description here

Could anybody explain why would this happen?

I tried using malloc() instead of calloc() but the existing array would also change.

Upvotes: 1

Views: 807

Answers (4)

Achal
Achal

Reputation: 11921

the statement a = (int*)calloc(10, sizeof(int)); allocates 10x4 i.e 40 bytes. lets say from 0x100 to 0x140 location.

    -----------------------------------------
   |     |    |    |   |    |    |      |    |
    -----------------------------------------
   0x100     ..      0x120                0x140
   a

next when you do realloc() on same a like p = realloc(a, 20); it won't add 20 bytes, it reduces whole memory to 20 bytes itself i.e from 0x100 to 0x120 and now when you access p[10] = 10; its out of bound i.e you are trying to put data in around 0x140 location which result in undefined behavior.

    --------------------
   |     |      |      | 
    --------------------
   0x100     ..      0x120 
   a                   
   p

from the man 3 realloc

The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size is larger than the old size, the added memory will not be initialized.

If you really want to expand existing memory by 20 bytes then do like

p = realloc(a ,20*sizeof(int));

Upvotes: 0

Abhishek Keshri
Abhishek Keshri

Reputation: 3234

p = realloc(a, 20);

In this statement, you are reallocating the p to 20/4 = 5.

Accessing undefined memory leads to undefined behavior. This means that compiler can behave any way: program crash, garbage value, sometimes correct results.

That's why you are getting garbage values after 5th element.

Edit it to: p = realloc(a, 20*sizeof(int));

Upvotes: 0

Ratul Sharker
Ratul Sharker

Reputation: 8013

From cppreference

The reallocation is done by either:

a) expanding or contracting the existing area pointed to by ptr, if possible. The contents of the area remain unchanged up to the lesser of the new and old sizes. If the area is expanded, the contents of the new part of the array are undefined.

b) allocating a new memory block of size new_size bytes, copying memory area with size equal the lesser of the new and the old sizes, and freeing the old block.

It depends on the implementation of the compiler and the size you're reallocating. If the newly allocated size is not occupi-able without fragment, then the realloc will definitely going to allocate memory in different location, which is more efficient than freeing already used up memory.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

This happens because you've re-allocated fewer items than originally allocated with calloc. The confusion is due to a slight difference in signatures of calloc and malloc/realloc. The call

a = calloc(10, sizeof(int));

allocates 10 blocks of sizeof(int), or 40 bytes on systems with sizeof(int) equal to 4, while

p = realloc(a, 20);

asks to reduce the size of that block to 20 bytes. In other words, calloc does multiplication by sizeof for you, while realloc and malloc require you to do multiplication yourself.

Once you told realloc that you want only 20 bytes, any access past the end of the fifth integer is undefined behavior.

If you want to extend the size to 20 ints, multiply by sizeof(int):

p = realloc(a, 20*sizeof(int));

Upvotes: 2

Related Questions