Home > Back-end >  Why do I get a "realloc(): invalid old size" error when executing?
Why do I get a "realloc(): invalid old size" error when executing?

Time:07-22

This is the error I get when executing the .exe file built from the code below:

*** Error in `./test_bin.exe': realloc(): invalid old size: 0x00007ffc67d00cf0 ***

I don't understand why realloc() throws an error when I'm using it as intended. I have tried casting before realloc() call, but that doesn't work either.

int main{

    double *test;
    double arr1[5] = {1.0,2.0,3.0,4.0,5.0};
    double arr2[2] = {1.0,2.0};
    int     i;


    test = (double*)malloc(5*sizeof(double));
    test = arr1;
    for(i=0;i<5;i  ) printf("%lf ",test[i]);

    printf("\n");

    test = realloc(test,2*sizeof(double));
    test = arr2;
    for(i=0;i<2;i  ) printf("%lf ",test[i]);
    printf("\n");
    return 0;

}

CodePudding user response:

From the documentation of realloc (emphasis is mine):

Reallocates the given area of memory. It must be previously allocated by malloc(), calloc() or realloc() and not yet freed with a call to free or realloc. Otherwise, the results are undefined.

In your case this line:

test = arr1;

Makes the pointer now point to the array arr1 on the stack. It is not a pointer received from malloc/calloc/realloc and therefore this is undefined behavior (UB).

Moreover - the chunk of memory you got from malloc (1 line before assigning the pointer to arr1) is now leaked. You cannot have access to it or free it.


Edit:
To complete the answer:
The citation above is somewhat conflicting with the fact that you can use realloc with a NULL pointer. The same documentation link above also mentions further down that-

If ptr is NULL, the behavior is the same as calling malloc(new_size).

But anyway this case also does not appy to your code (as the address of array on the stack is not NULL).

CodePudding user response:

You passed the pointer converted from arr1, which is not allocated via malloc() family, to realloc(). This invokes undefined behavior.

You can use memcpy() to copy contents of arrays instead of assigning pointers.

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

int main(void){

    double *test;
    double arr1[5] = {1.0,2.0,3.0,4.0,5.0};
    double arr2[2] = {1.0,2.0};
    int     i;


    test = malloc(5*sizeof(double));
    /* test = arr1; */
    memcpy(test, arr1, sizeof(arr1));
    for(i=0;i<5;i  ) printf("%lf ",test[i]);

    printf("\n");

    test = realloc(test,2*sizeof(double));
    /* test = arr2; */
    memcpy(test, arr2, sizeof(arr2));
    for(i=0;i<2;i  ) printf("%lf ",test[i]);
    printf("\n");
    return 0;

}

Also note that casting results of malloc() family is considered as a bad practice.

CodePudding user response:

These statements

test = (double*)malloc(5*sizeof(double));
test = arr1;

results in a memory leak because at first memory was allocated and its address was assigned to the pointer test and then the pointer test was reassigned with the address of the first element of the array arr1. So the address of the allocated memory was lost.

And you may reallocate only memory that early was dynamically allocated using malloc, calloc or realloc.

Arrays do not have the assignment operator. You need to copy elements from one array to another. For example

test = (double*)malloc(5*sizeof(double));
memcpy( test, arr1, 5 * sizeof( double ) );
for(i=0;i<5;i  ) printf("%lf ",test[i]);

Your program can look the following way

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

int main( void )
{
    double arr1[] = { 1.0, 2.0, 3.0, 4.0, 5.0 };
    const size_t N1 = sizeof( arr1 ) / sizeof( *arr1 );
    double arr2[] = { 1.0, 2.0 };
    const size_t N2 = sizeof( arr2 ) / sizeof( *arr2 );

    double *test = malloc( sizeof( arr1 ) );

    if ( test != NULL )
    {
        memcpy( test, arr1, sizeof( arr1 ) );
        for ( size_t i = 0; i < N1; i   )
        {
            printf( "%f ", test[i] );
        } 
        putchar( '\n' );

        double *tmp = realloc( test, sizeof( arr2 ) );

        if ( tmp != NULL )
        {
            test = tmp;

            memcpy( test, arr2, sizeof( arr2 ) );
            for ( size_t i = 0; i < N2; i   )
            {
                printf( "%f ", test[i] );
            } 
            putchar( '\n' );
        }

        free( test );
    }
}

The program output is

1.000000 2.000000 3.000000 4.000000 5.000000 
1.000000 2.000000 

Pay attention to that you need to use an intermediate pointer to reallocate memory. Otherwise again there can be a memory leak if the memory will not be reallocated successfully.

And the length modifier l in the format string "%lf" in the calls of printf is redundant and has no effect,

  • Related