I'm trying to learn the memory allocation in C using malloc and increasing the size of allocated array using realloc inside a function. I came across this. when I use single variable the code is working well. But when I allocate memory for second variable, it gives me weird output.
Code is below:
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
# define N 3
void padd(int *a){
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
}
int main()
{
int *d;
int *pA;
int size = N*sizeof(int);
pA = (void *)malloc(size);
//d = (int *)malloc(size);
padd(pA);
printf("outside func= %d",pA[0]);
}
it gives me output:
inside func= 10
outside func= 10
but if I uncomment the //d = (int *)malloc(size); line, It gives me
inside func= 10
outside func= -1368048824
as output.
What might be wrong here?
If realloc
can’t extend a buffer in place, it will allocate a new buffer, copy the contents of the old buffer to it, free the old buffer, and return the address of the new buffer (or NULL
if it cannot satisfy the request); thus, the value of a
can change in padd
. However, that change is only applied to the formal parameter a
- the actual parameter pA
is not affected.
Based on the behavior, it looks like that if you allocate d
, it’s allocated immediately after pA
such that pA
can’t be extended in place, so realloc
is creating a new buffer and deallocating the old one, and the old buffer is overwritten before the printf
statement in main
.
You’ll want to write padd
such that any changes to a
are reflected in pA
- either return the (potentially new) value of a
or pass a pointer to pA
:
void padd( int **a )
{
size_t sizes = 10 * sizeof (int); // see note 1
int *tmp = realloc( *a, sizes ); // see note 2
if ( tmp )
{
*a = tmp;
(*a)[0] = 10;
printf( "Inside func, (*a)[0] = %d\n", (*a)[0] );
}
else
{
printf ( "Inside func, realloc failed!\n" );
}
}
and you’d call it as
padd( &pA );
Note 1: sizeof
has type size_t
, not int
.
Note 2: Since realloc
can potentially return NULL
, always assign the result to a temporary value and check it before assigning back to the original variable, otherwise you run the risk of losing access to memory you’ve already allocated. Also, the cast to void *
is unnecessary and confusing since you’re assigning the result to an int *
variable. Unless you’re compiling this code as C++ or under an ancient K&R C compiler, just leave the cast off completely - otherwise, your cast has to match the type of the thing you’re assigning to, which in this case is int *
.