Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo
Memoria dinamica La memoria dinamica è la memoria gestita dinamicamente a run-time dal sistema operativo e dal programma (stack ed heap) E’ possibile (per un programma) allocare aree di memoria dinamicamente durante l’esecuzione ed accedere ad esse mediante puntatori. Gli oggetti così ottenuti sono detti dinamici ed allocati nella memoria libera.
Memoria stack L’area di memoria stack é quella in cui viene allocato un “pacchetto” di dati non appena l’esecuzione passa dal programma chiamante a una funzione. Questo “pacchetto” contiene: - l’indirizzo di rientro nel programma chiamante - la lista degli argomenti passati alla funzione - il valore di ritorno della funzione e viene “impilato” sopra il pacchetto precedente (quello del progr. chiamante) e poi automaticamente rimosso dalla memoria appena l’esecuzione della funzione é terminata.
Memoria stack Nella memoria stack vengono sistemati anche i dati relativi a tutte le variabili automatiche (cioè locali e non statiche) create dalla funzione. Il loro “tempo di vita” é legato all’esecuzione della funzione proprio perché, quando la funzione termina, l’intera area stack allocata viene rimossa.
Memoria heap Esiste un’altra area di memoria che il programma può utilizzare. Questa area, detta heap, è soggetta a regole completamente diverse da quelle che governano l’area stack. L’area heap non é allocata automaticamente, ma solo su esplicita richiesta del programma (allocazione dinamica della memoria) L’area allocata non é identificata da un nome, ma é accessibile solo tramite dereferenziazione di un puntatore
Memoria heap La sua visibilità é legata a quella della variabile puntatore che contiene il suo indirizzo Il suo tempo di vita coincide con l’intera durata del programma, a meno che non venga esplicitamente deallocata; se il puntatore va out of scope, l’area non é più accessibile, ma continua a occupare memoria inutilmente. L’allocazione dinamica della memoria si realizza tramite l’operatore prefisso new. La deallocazione di tale memoria si realizza tramite l’operatore unario delete.
Operatore new L’operatore new permette di allocare memoria per uno o più oggetti nell’area heap e ne restituisce l’indirizzo new tipo [dimensione] tipo é il tipo dell’oggetto (o degli oggetti) da creare dimensione é il numero degli oggetti, che vengono sistemati nella memoria heap consecutivamente; se questo operando é omesso, viene costruito un solo oggetto In caso di errore (memoria libera/dinamica non disponibile) restituisce il valore NULL
Esempi int* punt = new int; alloca un oggetto int nell’area heap e usa il suo indirizzo per inizializzare il puntatore punt; struct anagrafico { }; anagrafico* p; p = new anagrafico [100]; definisce la struttura anagrafico e dichiara un puntatore a tale struttura, a cui assegna l’indirizzo del primo di cento oggetti di tipo anagrafico, allocati nell’area heap.
Operatore delete L’operatore unario delete dealloca (libera) la memoria dell’area heap puntata dall’operando. int* punt = new int; allocazione delete punt; deallocazione L’operatore delete non cancella la variabile puntatore né altera il suo contenuto: l’unico effetto é di liberare la memoria puntata rendendola disponibile per eventuali ulteriori allocazioni.
Operatore delete L’operatore delete può essere applicato solo ad un puntatore che indirizza un oggetto allocato mediante una new mantenendo la correttezza semantica dell’operazione. Non esiste alcun controllo sull’uso congruente degli operatori new e delete, sono sotto la sola gestione del programmatore.
Operatore delete Se delete punta a un’area in cui sono stati allocati più oggetti, l’operatore va ulteriormente specificato con una coppia di parentesi quadre (senza la dimensione, che il C++ é in grado di riconoscere automaticamente). float * punt = new float [100]; ( alloca 100 oggetti float ) delete[] punt; (libera tutta la memoria allocata)
Operatore delete L’operatore delete costituisce l’unico mezzo per deallocare memoria heap, che, altrimenti, sopravvive fino alla fine del programma, anche quando non é più raggiungibile. int* punt = new int; ( alloca un intero nell’area heap) int a; ( definisce la variabile a intera) punt = &a; (assegna a punt l’indirizzo di a) L’oggetto intero dell’area heap non é più raggiungibile in quanto con l’ultima assegnazione si è distrutto il valore iniziale di p (indirizzo ritornato da new) !