L’accesso alla memoria dynamic funziona solo all’interno della funzione

Questa domanda è pensata per essere usata come duplicato canonico per questa FAQ:

Sto allocando i dati dynamicmente all’interno di una funzione e tutto funziona bene, ma solo all’interno della funzione in cui avviene l’allocazione. Quando tento di utilizzare gli stessi dati al di fuori della funzione, si verificano arresti anomali o altri comportamenti imprevisti del programma.

Ecco un MCVE:

#include  #include  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 } 

Ogni volta che viene chiamato print_array all’interno della funzione create_array , ottengo l’output previsto 0 1 2 3 4 , ma quando lo chiamo da main , ottengo un arresto anomalo del programma.

Qual è la ragione di questo?

La ragione di questo errore è che i data utilizzati dalla funzione create_array sono una variabile locale che esiste solo all’interno di quella funzione. L’indirizzo di memoria assegnato ottenuto da malloc viene memorizzato solo in questa variabile locale e non viene mai restituito al chiamante.


Considera questo semplice esempio:

 void func (int x) { x = 1; printf("%d", x); } ... int a; func(a); printf("%d", a); // bad, undefined behavior - the program might crash or print garbage 

Qui, una copia della variabile a è memorizzata localmente all’interno della funzione, come il parametro x . Questo è noto come pass-by-value .

Quando x viene modificato, viene modificata solo la variabile locale. La variabile a nel chiamante rimane invariata, e poiché a non è inizializzata, conterrà “garbage” e non può essere utilizzata in modo affidabile.


I puntatori non fanno eccezione a questa regola del pass-by-value. Nell’esempio, i data variabile puntatore data passati per valore alla funzione. Il puntatore di data all’interno della funzione è una copia locale e l’indirizzo assegnato da malloc non viene mai restituito al chiamante.

Quindi la variabile puntatore nel chiamante rimane non inizializzata e quindi il programma si blocca. Inoltre, la funzione create_array ha anche creato una perdita di memoria , poiché dopo l’esecuzione di questa funzione, non vi è più alcun puntatore nel programma che tiene traccia di quel blocco di memoria allocata.


Esistono due modi per modificare la funzione in modo che funzioni come previsto. O restituendo una copia della variabile locale al chiamante:

 int* create_array (int size) { int* data = malloc(sizeof(*data) * size); for(int i=0; i 

oppure passando l'indirizzo alla variabile del puntatore del chiamante e scrivendo direttamente alla variabile del chiamante:

 void create_array (int** data, int size) { int* tmp = malloc(sizeof(*tmp) * size); for(int i=0; i 

Qualsiasi forma va bene.