martedì 27 novembre 2012

Uso dell'operatore delete

Diversamente dalla memoria locale sullo stack, la memoria del heap deve essere semplicemente liberata. Un volta conclusa l'operazione con il blocco di memoria allocato con l'operatore new, deve essere liberato con l'operatore delete. Questo è ciò che viene fatto nel programma con il blocco di memoria heap che ha immagazzinato 20.
delete pHeap;
La memoria viene restituita a heap per uso futuro. I dati che sono stati immagazzinati non sono più disponibili. Nella riga seguente viene liberata anche la memoria di pHeap2. Un importante argomento da comprendere è che le due istruzioni liberano la memoria su heap ma non interagiscono sulle variabili locali pHeap e pHeap2. Questo crea un potenziale problema in quanto i puntatori segnano una locazione che può essere assegnata dal computer a qualsiasi altra operazione. Questi puntatori sono chiamati puntatori appesi e sono da evitare. Una via per gestire i puntatori appesi è di assegnare valore 0 a loro, il quel viene fatto nel programma con le seguenti istruzioni.

    pHeap =0;
    pHeap2 =0;
Un altro metodo per gestirli è di assegnare loro un indirizzo valido di memoria.

Evitare perdite di memoria

Un problema che il programmatore deve evitare è di allocare memoria e perdere la possibilità di gestirla in qualche modo per poterla liberare in seguito. Quando la memoria viene persa questo è chiamato memory leak. In un programma di grandi dimensioni questo può comportare un vasto problema sino a provocare il crash del sistema. Come programmatore è necessario evitare le perdite di memoria. Nel programma Heap sono state inserite due funzioni le quali creano perdite di memoria, come esempio, in modo da mostrare come non gestire la memoria dinamica in un programma. Nella prima funzione perdita1(), viene allocato un blocco di memoria per un valore intero e quindi si conclude.

 void perdita1()
{ int* dripeti1 = new int(40); }
Se viene chiamata questa funzione, la memoria viene persa per sempre durante il funzionamento del programma. Il problema è che dripeti1, è il solo collegamento con il blocco appena acquisito di memoria su heap, quando la variabile locale cessa di esistere, la funzione perdita1() si conclude. Così non esiste un modo per accedere alla memoria allocata. Per evitare questa perdita di memoria si possono fare due cose, usare l'istruzione delete per liberare la memoria o restituire una copia di dripeti1, e liberare la memoria in un'altra parte del programma.
La seconda funzione creata è perdita2().

void perdita2()
{ int* dripeti2 = new int(50);
dripeti2 = new int(200);
delete dripeti2;
}
In questo caso la perdita di memoria è più sottile, ma esiste comunque. La prima linea della funzione, alloca un blocco di memoria su heap al quale assegna un valore di 50, e dripeti2 punta ad esso. Tuttavia nella seconda istruzione viene, a dripeti2, assegnato un nuovo blocco di memoria al quale viene attribuito valore 200. Infine si cancella il contenuto del blocco di memoria dripeti2. Il problema è che il blocco al quale era stato assegnato valore 50 non ha più alcun puntatore che fa riferimento ad esso e pertanto non può essere liberato. Questo è un altro esempio di perdita di memoria del programma. In questo caso dripeti2 è un puntatore appeso, ma del quale non bisogna preoccuparsi in quanto cessa di esistere al termine della funzione.

Nessun commento:

Posta un commento