Liberare la memoria

  1. malloc riserva una zona di memoria
  2. free libera questa zona, ossia dice che questa zona non mi serve più, e può quindi venire riutilizzata
  3. il vantaggio è che la memoria liberata può ora venire riusata per altri scopi
  4. cosa succede se si fa una sequenza di malloc senza free
  5. cosa succede se si fa la free

La funzione malloc serve a chiedere una nuova zona di memoria da usare. Quello che succede quando viene chiamata la funzione è che il calcolatore individua una zona di memoria libera, ossia una zona che non è attualmente occupata da variabili o usata in altro modo, e ne restitusce l'indirizzo iniziale. Da questo momento in poi, la zona di memoria non è più libera, ma è attualmente in uso. Questa zona non deve quindi venire più trattata come una zona libera, per cui non deve essere usata per altre variabili e non deve venire restituita da successive chiamata della funzione malloc. Se cosí non fosse, si potrebbero verificare situazioni in cui due puntatori, che ci aspettiamo non essere correlati, puntano a una stessa locazione, con conseguenti effetti inattesi.

Quando una zona di memoria non serve più, occorre rilasciarla chiamando la funzione free. Questa funzione dice che la zona di memoria non ci serve più, e che può quindi venire usata in altro modo.

Il vantaggio di chiamare la funzione free è che, in questo modo, la memoria non più utilizzata dal programma può venire ``riciclata'', ossia riutilizzata. Si considerino i due programmi seguenti nolibera.c e libera.c. Il primo continua ad allocare sempre nuovi blocchi di memoria. Quando tutta la memoria è stata assegnata, non esistono più parti di memoria libere. Da questo momento in poi, le chiamate alla funzione malloc falliscono (viene restituito NULL), dal momento che questa funzione non riesce più a trovare una zona di memoria libera da allocare.

/*
  Alloca memoria senza mai liberarla.
*/

#include<stdlib.h>

int main() {
  int i;
  int *p;


  for(i=0; i<=100000; i++) {

		/* alloca cinquantamila interi */
     p=malloc(50000*sizeof(int));
     if(p==NULL) {
       printf("Impossibile allocare altra memoria\n");
       exit(1);
     }
  }

  return 0;
}

Al contrario, il programma libera.c libera la memoria. In questo modo, la memoria che non serve più viene rilasciata, e può quindi venire usata di nuovo.

/*
  Alloca memoria e la libera.
*/

#include<stdlib.h>

int main() {
  int i;
  int *p;


  for(i=0; i<=100000; i++) {

		/* alloca cinquantamila interi */
     p=malloc(50000*sizeof(int));
     if(p==NULL) {
       printf("Impossibile allocare altra memoria\n");
       exit(1);
     }


		/* libera la memoria */
     free(p);
  }

  return 0;
}

La differenza fra il primo programma e il secondo è che il primo programma continua a riservare zone di memoria, anche se non vengono più usate.

Lo stato della memoria dopo la prima chiamata alla funzione malloc è quella a fianco per tutti e due i programmi: le zone di memoria riservate (non libere) sono quella di p e quella che è stata riservata dalla funzione malloc

Quando si fa la seconda chiamata, la memoria che è stata allocata in precedenza risulta riservata, quindi la funzione malloc è costretta a usare una differente zona di memoria, che viene a sua volta riservata. Lo stato della memoria è quindi quello qui sotto.

È chiaro che, se si continuano ad allocare sempre nuove zone di memoria, alla fine non ci sarà più memoria disponibile.

Al contrario, il secondo programma libera la memoria. Quindi, dopo la prima chiamata alla funzione malloc, e dopo la chiamata alla funzione free, la zona allocata viene marcata come ``non più usata'', e quindi può venire allocata dalla successiva chiamata alla funzione malloc.

Si può quindi dire che la memoria libera (non allocata, ossia che non è attualmente riservata) è tornata ad essere quella che era prima della prima chiamata alla funzione malloc. La zona di memoria che è stata liberata con free è ora libera. Quindi, la seconda chiamata a malloc potrebbe restituire la stessa zona. La cosa essenziale, comunque, è che la quantità di memoria libera dopo aver fatto malloc e poi free è la stessa di partenza.

Nota: la funzione free, dal momento che il puntatore viene passato per valore, non può modificare il valore del puntatore, quindi il puntatore non vale NULL dopo la chiamata. Nel puntatore c'è ancora l'indirizzo della zona precedentemente allocata. Dal momento che questa zona è ora libera, può venire riallocata e modificata, quindi ogni accesso a questa zona (usando p[i] oppure *p) è da considerarsi un errore di programmazione.