Scopriamo cos’è e come utilizzare la memoria dinamica heap in C.
Quando parliamo di memoria dinamica in C ci stiamo riferendo all’heap. L’heap è appunto una porzione di memoria che non ha dimensione fissa e che, a differenza dello stack, aumenta e diminuisce nel corso dell’esecuzione di un programma. Proprio per questo è definita dinamica.
La memoria nello stack viene allocata a compile time, questo significa che la struttura della memoria viene decisa prima che il programma venga eseguito e che indipendentemente dalle operazioni che vi si faranno, la memoria utilizzata sarà sempre la stessa. La memoria dinamica invece viene allocata a runtime e quindi solo quando ce n’è veramente bisogno.
Per dichiarare una variabile nell’heap dobbiamo utilizzare la funzione malloc(), che riserva una porzione di memoria. Per accedervi dovremo usare il puntatore che ci viene ritornato da malloc. Utilizziamo sizeof() all’interno di malloc per ottenere la dimensione di byte di un tipo di variabile. Se dobbiamo allocare la memoria per un array dovremmo moltiplicare questo valore per il numero di elementi.
Le variabili salvate nell’ Heap sono utilizzabili nel nostro programma solo tramite puntatori, per questo è importante non perdere il loro indirizzo di memoria.
Ora che utilizziamo la memoria dinamica è bene tener presente che quando allochiamo della memoria con malloc, questa rimarrà allocata fino a che il programma non termina. Questo potrebbe portare al famigerato memory leak, che si verifica quando si perde traccia di una variabile, e che nel peggiore dei casi potrebbe riempire tutta la memoria del sistema e mandarlo in crash.
Per liberare memoria prima che il programma termini si può utilizzare la funzione free, che dato in input un puntatore, deallocherà l’indirizzo di memoria a cui si riferisce. E’ buona regola per evitare memory leak chiamare free quando si ha finito di utilizzare una variabile.
Scriviamo un programma per mettere in pratica quello che abbiamo imparato.
#include <stdio.h>
//Malloc è contenuto in stdlib.h
#include <stdlib.h>
int main(){
int i;
//Dichiaro un puntatore
int *p;
double *p2;
//Alloco la memoria per un tipo int
p = malloc( sizeof( int ));
//Assegno un valore alla variabile nell heap
*p = 100;
//Stampo il suo contenuto
printf("Variabile in heap: %d \n",*p);
//Dealloco la memoria, non uso più la variabile int associata
free(p);
//Alloco la memoria per un array di 5 elementi di tipo double
p2 = malloc( sizeof( double ) * 5);
//Riempio l'array
for(i=0; i<5; i++){
//Riempio l'array con dei numeri con virgola
p2[i] = 0.5 * i;
}
//Stampo l'array
for(i=0; i<5; i++){
//Riempio l'array con dei numeri con virgola
printf("%lf ",p2[i]);
}
//Dealloco la memoria, non uso più l'array
free(p2);
return 0;
}
Varabile in Heap: 50
Array in Heap: 0.00 0.50 1.00 1.50 2.00