Storia della questione:
I meccanismi di dynamic memory allocation sono comparsi in C insieme alle funzioni della libreria standard malloc/free in <stdlib.h>. Hanno permesso di implementare strutture di dimensioni variabili, collezioni complesse e oggetti, dando un forte impulso allo sviluppo del linguaggio e al suo utilizzo nella programmazione su larga scala.
Problema:
Lavorare con la memoria dinamica richiede al programmatore un controllo completo sul ciclo di vita degli oggetti. Errori (memory leak, doppio rilascio, uso errato dei puntatori) possono portare a crash o vulnerabilità (ad esempio, exploit tramite errori use-after-free).
Soluzione:
— Controllare sempre i valori restituiti da malloc/calloc/realloc. Se l'allocazione fallisce, restituiscono NULL. — Quando si rilascia la memoria, impostare il puntatore su NULL per evitare l'uso di un blocco liberato. — Non utilizzare il puntatore dopo free. — Mantenere una corrispondenza corretta tra malloc/free e calloc/free.
Esempio di codice:
#include <stdio.h> #include <stdlib.h> int main() { int *arr = malloc(5 * sizeof(int)); if (!arr) { perror("Memoria non allocata"); return 1; } for (int i = 0; i < 5; ++i) arr[i] = i * i; for (int i = 0; i < 5; ++i) printf("%d ", arr[i]); printf(" "); free(arr); arr = NULL; return 0; }
Caratteristiche chiave:
Cosa succede liberando la memoria allocata tramite malloc con l'operatore delete o viceversa (in C++)?
Non si possono mescolare i meccanismi di allocazione e rilascio di memoria tra i linguaggi (C/C++). In C, solo malloc/free, in C++ new/delete.
Cosa succede se si chiama free(NULL)?
free(NULL) è sicuro (questo è garantito dalla norma C). Tale chiamata non fa nulla.
È possibile utilizzare realloc per aumentare o diminuire il blocco di memoria e cosa succede con il puntatore originale?
realloc può spostare il blocco di memoria, e se ciò accade, il vecchio puntatore diventa non valido. Assegna sempre un nuovo puntatore:
ptr = realloc(ptr, new_size);
Si allocava memoria per un array in un ciclo, ma si dimenticava di rilasciarla alla fine dell'iterazione. Durante la notte, il programma ha "consumato" tutta la RAM sul server.
Pro:
Contro:
In un ciclo, la memoria veniva sempre rilasciata dopo l'uso, tutti i controlli su NULL venivano effettuati immediatamente dopo malloc, utilizzando strumenti di debug per il monitoraggio dei leak.
Pro:
Contro: