This question is meant to be used as a canonical duplicate for this FAQ:
I am allocating data dynamically inside a function and everything works well, but only inside the function where the allocation takes place. When I attempt to use the same data outside the function, I get crashes or other unexpected program behavior.
Here is a MCVE:
#include <stdlib.h>
#include <stdio.h>
void print_array (int* data, int size)
{
for(int i=0; i<size; i++)
{
printf("%d ", data[i]);
}
printf("\n");
}
void create_array (int* data, int size)
{
data = malloc(sizeof(*data) * size);
for(int i=0; i<size; i++)
{
data[i] = i;
}
print_array(data, size);
}
int main (void)
{
int* data;
const int size = 5;
create_array(data, size);
print_array(data, size); // crash here
free(data);
}
Whenever print_array
is called from inside the create_array
function, I get the expected output 0 1 2 3 4
, but when I call it from main
, I get a program crash.
What is the reason for this?
The reason for this bug is that the
data
used by thecreate_array
function is a local variable that only exists inside that function. The assigned memory address obtained frommalloc
is only stored in this local variable and never returned to the caller.Consider this simple example:
Here, a copy of the variable
a
is stored locally inside the function, as the parameterx
. This is known as pass-by-value.When
x
is modified, only that local variable gets changed. The variablea
in the caller remains unchanged, and sincea
is not initialized, it will contain "garbage" and cannot be reliably used.Pointers are no exception to this pass-by-value rule. In your example, the pointer variable
data
is passed by value to the function. Thedata
pointer inside the function is a local copy and the assigned address frommalloc
is never passed back to the caller.So the pointer variable in the caller remains uninitialized and therefore the program crashes. In addition, the
create_array
function has also created a memory leak, since after that function execution, there is no longer any pointer in the program keeping track of that chunk of allocated memory.There are two ways you can modify the function to work as expected. Either by returning a copy of the local variable back to the caller:
or by passing the address to the caller's pointer variable and write directly to the caller variable:
Either form is fine.