Concetti Chiave
- L'allocazione dinamica della memoria in C/C++ avviene durante l'esecuzione del programma tramite funzioni come malloc() e calloc().
- Il programmatore ha la responsabilità di gestire la creazione e la distruzione degli oggetti dinamici, utilizzando funzioni come free() e realloc().
- È importante azzerare i puntatori dopo la deallocazione per evitare riferimenti fluttuanti (dangling references) e problemi di gestione della memoria.
- C++ introduce operatori come new e delete per gestire l'allocazione e la deallocazione della memoria in modo più semplice rispetto al C.
- La vita degli oggetti dinamici inizia con la loro allocazione e termina con la deallocazione, evidenziando l'importanza di un'adeguata gestione della memoria.
L’allocazione dinamica della memoria è l’allocazione eseguita durante l’esecuzione del pgm, in base ad esplicite istruzioni scritte nel pgm stesso.
In C/C++ è il programmatore che decide la loro creazione e distruzione.
Area di memoria: Heap
#define NULL 0 in
Operatore unario: sizeof(tipo|var) restituisce la dimensione in byte di un oggetto.
L’operatore sizeof, simile ad una funzione, ritorna un tipo speciale, usato per le dimensioni di memoria: size_t
In
void * malloc (size_t dim);
Alloca un blocco di memoria di dim byte
Restituisce un puntatore generico al blocco di memoria (oppure NULL, se non c’è memoria disponibile).
Testare il puntatore (se uguale a NULL chiamare la exit() )
void * calloc (size_t num, size_t size);
Alloca num elementi consecutivi di memoria di dimensione size (inizializzandola a zero).
Serve ad allocare sequenze contigue di aree di memoria (array).
Restituisce un puntatore generico al blocco di memoria (oppure NULL, se non c’è memoria a disposizione).
double * punt, * punt2;
punt = (double *) calloc(10, sizeof(double));
Più interessante:
punt2 = (double *) calloc(var, sizeof(double));
Si può ottenere la stessa cosa anche con la malloc():
punt2 = (double *) malloc(var* sizeof(double));
void free (void * punt);
Rende nuovamente disponibile lo spazio di memoria (il blocco di memoria) puntato da punt. Se punt è uguale a NULL, la free() non fa nulla.
E’ buona norma “azzerare” i puntatori sui quali è stata effettuata una free(), in modo che non puntino più all’area ora libera.
free(punt);
punt = NULL;
realloc()
void * realloc (void * punt, size_t newSize);
Cambia la dimensione (si può solo aumentarla) di un blocco di memoria
allocata.
Per maggiori informazioni consulta l’Help.
La vita di un oggetto dinamico inizia dalla sua creazione(allocazione, malloc(), calloc()) e finisce con la sua distruzione (deallocazione, free()) o alla fine del programma.
Ci sono due tecniche di recupero della memoria:
1) a carico del programmatore (Pascal, C, C++, …)
2) garbage collector (Lisp, Eiffel, Java, …)
Gestione della memoria in C++
C++
Operatori:
new
delete
delete [ ]
Esempi:
punt = new tipoDiDato;
delete punt;
puntVett = new tipoDiDato [const|var];
delete [ ] puntVett;
typedef struct{
char nome [21];
char cognome [25];
char indirizzo [30];
char professione [15];
}persona;
int main()
{
persona * p;
int i;
p=(persona *) malloc (numElem*sizeof(persona));
if(!p)
printf(“Memoria insufficiente\n”);
else
{
for(i=0; i
{
gets((p+i) nome);
….
}
}
}
Produzione di spazzatura (garbage)
Dangling references (riferimenti fluttuanti/pendenti)
Effetti collaterali
Se in una funzione, dopo aver allocato (nello stack) un puntatore e un’area dinamica (nello heap, assegnando al puntatore l’indirizzo dell’area), dimentichi di deallocare l’area prima che la funzione termini, produci garbage.
Un puntatore che punta a locazioni di memoria non significative prende il nome di dangling reference.
Domande da interrogazione
- Cos'è l'allocazione dinamica della memoria e come viene gestita in C/C++?
- Qual è la differenza tra malloc() e calloc()?
- Come si gestisce la deallocazione della memoria in C/C++?
- Quali sono le tecniche di recupero della memoria e come differiscono?
L'allocazione dinamica della memoria avviene durante l'esecuzione del programma, basandosi su istruzioni scritte nel codice. In C/C++, è il programmatore a decidere la creazione e la distruzione degli oggetti dinamici, utilizzando funzioni come malloc() e free().
La funzione malloc() alloca un blocco di memoria di una dimensione specificata, mentre calloc() alloca un numero di elementi di una certa dimensione, inizializzando la memoria a zero. Entrambe restituiscono un puntatore generico o NULL se non c'è memoria disponibile.
La deallocazione della memoria si gestisce tramite la funzione free(), che rende nuovamente disponibile lo spazio di memoria puntato. È buona norma azzerare il puntatore dopo la deallocazione per evitare riferimenti fluttuanti.
Ci sono due tecniche di recupero della memoria: una a carico del programmatore, utilizzata in linguaggi come C e C++, e l'altra gestita da un garbage collector, presente in linguaggi come Lisp e Java. La prima richiede che il programmatore gestisca manualmente la memoria, mentre la seconda automatizza il processo.