Emirhan G.
Emirhan G.

Reputation: 7

Using 'realloc()' during runtime gives crash, why? - C Language

I have an array that I want to increase the size of during runtime. I assign values to the elements of the array by using a loop, and when the index of the loop hits the number of elements of the array, I want to increase the size of the array.

What I did, actually works; I can assign values to elements of the array that I would normally not be able to assign any values to without increasing the array's size. The bad side is, it gives me a crash after the program runs and finishes smoothly. What is wrong here? Is it that maybe the memory that I try to allocate for the array is already filled?

int main()
{
    int arr[3];
    int num_of_elements = sizeof(arr)/sizeof(arr[0]); // This gives '3', I checked

    for(i = 0; i < 10; i++)
    {  
        if(i == num_of_elements)
        {
            num_of_elements = num_of_elements + 10;
            realloc(arr, num_of_elements);
        }
        arr[i] = i+10;
        printf("%d\n", arr[i]);
    }

    return 0;
}

Upvotes: 1

Views: 346

Answers (2)

user2736738
user2736738

Reputation: 30906

Well you are invoking undefined behavior. From standard §7.22.3.5

void *realloc(void *ptr, size_t size);

If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to the free or realloc function, the behavior is undefined. If memory for the new object cannot be allocated, the old object is not deallocated and its value is unchanged.

By memory management function - it means malloc etc. arr is not dynamically allocated memory. So passing this to realloc is undefined behavior - in your case that behavior leads you to crash in program.

It would work if you do this

int *arr = malloc(sizeof(int)*3);
if( arr == NULL){
  perror("Malloc failed");
  exit(EXIT_FAILURE);
}

...
int *p = realloc(arr,num_of_elements*sizeof(int));
                       ^^^^^
if(p == NULL ){
   perror("realloc failed");
   exit(EXIT_FAILURE);
}
arr = p;

Check how realloc is used.

The takeaways will be:-

  • Check the return value of realloc, malloc.
  • You were trying to reallocate extra 10 elements for which you need 10*sizeof(int) amount of memory.
  • Don't do arr = realloc(arr,SIZE) in case realloc fails you will have memory leak.

Why realloc to p after all you do arr=p annyway?

Two reasons so far

  • The answer to this is when realloc fails then it returns NULL now if you assign arr to NULL then you may have a situation where you lose the only reference to the previously allocated memory - leading to a memory leak. That's why we do it like this.

  • Note this from standard

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.

Notice that may part - it might be the same address as before as pointed by arr or it might be different one. That explains why we should store it in some temporary pointer and then we assign it later.

Upvotes: 5

iBug
iBug

Reputation: 37217

You should have done this:

arr = realloc(arr, num_of_elements);
^^^^^

realloc() does not necessarily extend or shrink the allocated memory in-place, it invalidates the dynamic memory that its first argument points to and allocates new memory, while preserving the content of the previous memory.

One possible implementation is :

void* realloc(void* ptr, size_t size) {
    void* ret = malloc(size);
    if (ret == NULL) return ret;
    if (ptr != NULL) {
        memcpy(ret, ptr, /* previous size from system */);
        free(ptr);
    }
    return ret;
}

Upvotes: 1

Related Questions