You are on page 1of 4

Allocazione dinamica della memoria Memoria stack e memoria dinamica (free store memory) Abbiamo gi parlato dell'area di memoria

stack: quella in cui viene allocato un pacchetto di dati non appena l'esecuzione passa dal programma chiamante a una funzione. Abbiamo detto che questo pacchetto (che contiene l'indirizzo di rientro nel programma chiamante, la lista degli argomenti passati alla funzione e tutte le variabili automatiche definite nella funzione) viene "impilato" sopra il pacchetto precedente (quello del programma chiamante) e poi automaticamente rimosso dalla memoria appena l'esecuzione della funzione terminata. Sappiamo anche che, grazie a questo meccanismo, le funzioni possono essere chiamate ricorsivamente e inoltre si possono gestire funzioni con numero variabile di argomenti. Le variabili automatiche definite nella funzione hanno lifetime limitato all'esecuzione della funzione stessa proprio perch, quando la funzione termina, il corrispondente pacchetto allocato nell'area stack viene rimosso. Un'altra area di memoria quella in cui vengono allocate le variabili non locali e le variabili locali statiche. A differenza dalla precedente, quest'area viene mantenuta in vita fino alla fine del programma, anche se ogni variabile visibile solo all'interno del proprio ambito. Esiste una terza area di memoria che il programma pu utilizzare. Questa area, detta free store memory (o heap nel linguaggio C), soggetta a regole di visibilit e tempo di vita diverse da quelle che governano le due aree precedenti, e precisamente:

l'area free store non allocata automaticamente, ma pu essere allocata o rimossa solo su esplicita richiesta del programma (allocazione dinamica della memoria); l'area allocata non identificata da un nome, ma accessibile esclusivamente tramite un puntatore; il suo scope coincide con quello del puntatore che contiene il suo indirizzo; il suo lifetime 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: si verifica l'errore di memory leak, opposto a quello di dangling references.

Operatore new

In C++, l'operatore new costruisce uno o pi oggetti nell'area free store e ne restituisce l'indirizzo. In caso di errore (memoria non disponibile) restituisce NULL. Gli operandi di new (tutti alla sua destra) sono tre, di cui solo il primo obbligatorio (le parentesi quadre nere racchiudono gli operandi opzionali): new tipo [[dimensione]] [(valore iniziale)]
tipo il tipo (anche astratto) dell'oggetto (o degli oggetti) da creare; dimensione il numero degli oggetti, che vengono sistemati nella memoria free store consecutivamente (come gli elementi di un array); se questo operando omesso, viene costruito un solo oggetto; se presente, l'indirizzo restituito da new punta al primo oggetto; valore iniziale il valore con cui l'area allocata viene inizializzata (deve essere dello stesso tipo di tipo); se omesso l'area non inizializzata.

NOTA: si potuto riscontrare che a volte i due operandi opzionali sono mutuamente incompatibili (alcuni compilatori pi antichi danno errore): in pratica (vedremo perch parlando dei costruttori), se il tipo nativo inizializza comunque tutti i valori con zero, se il tipo astratto funziona bene (a certe condizioni). Ovviamente l'operatore new non pu restituire un l-value; pu essere invece un r-value sia nelle inizializzazioni che nelle assegnazioni, e pu far parte di operazioni di aritmetica fra puntatori . Esempi: inizializzazione: int* punt = new int (7);

assegnazione con operazione aritmetica: struct anagrafico { ....... } ; anagrafico* p_anag ; p_anag = new anagrafico [100] + 9 ; nel primo esempio alloca un oggetto int (inizializzato con il valore 7) nell'area free store e usa il suo indirizzo per inizializzare il puntatore punt; nel secondo esempio definisce la struttura anagrafico e definisce un puntatore a tale struttura, a cui assegna l'indirizzo del decimo di cento oggetti di tipo anagrafico, allocati nell'area free store.

Operatore delete

In C++, l'operatore binario delete (con un operando opzionale e l'altro obbligatorio) dealloca la memoria dell'area free store puntata dall'operando (obbligatorio). Non restituisce alcun valore e quindi deve essere usato da solo in un'istruzione (non essendo n un l-value n un r-value non pu essere usato in un'espressione con altre operazioni).

Es.:

allocazione: deallocazione:

int* punt = new int ; delete punt ;

Contrariamente all'apparenza l'operatore delete non cancella il puntatore n altera il suo contenuto: l'unico effetto di liberare la memoria puntata rendendola disponibile per ulteriori allocazioni (se l'operando non punta a un'area free store alcuni compilatori generano un messaggio di errore (o di warning), altri no, ma in ogni caso l'operatore delete non ha effetto). Se l'operando punta a un'area in cui stato allocato un array di oggetti, bisogna inserire dopo delete l'operando opzionale, che consiste in una coppia di parentesi quadre (senza la dimensione dell'array, che il C++ in grado di riconoscere automaticamente).

Es.:

float* punt = new float [100] ; delete [ ] punt ;

(alloca 100 oggetti float ) (libera tutta la memoria allocata)

L'operatore delete costituisce l'unico mezzo per deallocare memoria free store, che, altrimenti, sopravvive fino alla fine del programma, anche quando non pi raggiungibile.

Es.: int* punt = new int ; int a ; punt = &a ;

(alloca un oggetto int nell'area heap e inizializza punt con il suo indirizzo) (definisce un oggetto int nell'area stack) (assegna a punt un indirizzo dell'area stack; l'oggetto int dell'area heap non pi raggiungibile)

Esempio: con uso puntatori ed operatori new e delete per allocare dinamicamente
#include <iostream>

#include <cstdlib> using namespace std; int main() { int *p; p=new int;

// uso variabile puntatore

if(p==NULL) cout <<"impossibile allocare\n"; *p =20; cout <<*p<<"\n"; // stampa 20 if (p) delete p; // allocazione dinamica di array int dim = 0; int*punt; cout<<"Digita numero di elementi " ; cin >> dim; punt = new int[dim]; if(!punt) { // gestione errore // uso if (punt) delete (punt);

// allocazione dinamica di array bidimensionale int num_r=0; int num_col=0; int**pu; // doppio puntatore a int cout <<"righe "; cin >>num_r; cout <<"colonne "; cin >>num_col; pu=new int*[num_r]; if(pu==NULL) { // gestione errore } for (int i=0;i<num_r; i++) { pu[i]=new int [num_col]; if(pu==NULL) { // . gestione errore } } // uso for (int i =0; i<num_r;i++) { if(!pu[i]) delete pu; } if(!pu) delete pu; system("Pause"); return (0); }

You might also like