Cerca nel blog

Loading

28 gennaio 2008

Stack o heap? Ovvero la gestione della memoria


Per la maggior parte dei neofiti programmatori, la gestione avanzata della memoria e' un concetto ostico da digerire specialmente perche' si utilizzano termini non sempre molto chiari. Lo scopo di questo post e' cercare di rendere piu' assimilabile la gestione della memoria nella programmazione C++.

Cominciamo a vedere cosa succede quando viene eseguito il nostro programma di test. Quando l'eseguibile viene caricato in memoria, questa viene suddivisa in tre segmenti: il code segment, lo stack segment e l'heap segment.

Per meglio capire l'organizzazione della memoria consideriamo il seguente codice sorgente. Si tratta di un codice completamente inutile, ma ci permette di capire come funzionano le cose.

int funzione(int par1, double par2, bool par3) {

   // definisci alcune variabili
   int temp1, temp2, temp3;
   float temp4, temp5, temp5;

   // fai qualcosa
   // ...

   // ritorna
   return 0;

}


int main(int argc, char ** argv) {

   // definisci alcune variabili
   bool isRunning = true;
   double myFloat = sqrt(2);

   // chiama funzione
   int mioInt = funzione( argc, myFloat, isRunning );

   // ritorna
   return 0;

}


Il code segment e' la memoria utilizzata per contenere la versione in linguaggio macchina del codice stesso, ovvero in parole molto povere, e' il posto dove la sequenza di operazioni da effettuare viene immagazzinata durante tutta l'esecuzione del programma.

Lo stack segment e' una regione di memoria organizzata come "Last In First Out". Il programma inizia con l'esecuzione del main e tutte le variabili ivi dichiarate vengono allocate nel stack e vi restano fino a quando escono di scope, ovvero fino a quando il main esce e il programma si ferma. Quando funzione viene chiamata, i suoi parametri vengono allocati nello stack contestualmente a tutte le variabili dichiarate all'interno. Anche in questo caso, la memoria occupata da temp1 ... temp5 verra' liberata non appena termina l'esecuzione di funzione. Questo dovrebbe spiegare perche' lo stack e' una memoria LIFO. E' proprio questo riciclo della memoria che rende pericoloso l'uso di variabili non inizializzate; infatti quando una variabile viene deallocata, la memoria fisica corrispondente viene riassegnata la prossima volta che viene richiesta senza pulirne il contenuto.
Concludendo possiamo dire che finiscono nello stack tutte le variabili allocate in modo "statico" ovvero senza utilizzare gli operatori new e new [].

Veniamo ora all'heap segment. Questo e' una regione piu' stabile della memoria e puo' essere utilizzata come shared memory tra differenti funzioni. Per creare una variabile nell'heap dobbiamo usare gli operatori new o new [] e, una volta creata, vi ci resta per fino a quando o viene distrutta dall'operatore delete o delete [] o al termine del programma.

Vediamo alcuni esempi pratici.

Esempio 1:
// .....
{ int inutile; }


In questo spezzone di codice, la variabile inutile viene creata all'interno di uno scope praticamente vuoto. In questo caso la regione di memoria corrispondente ad inutile viene creata nello stack e subito dopo de-allocata senza che questa possa mai venir utilizzata.


Esempio 2:

{
   // ....

   MyClass * miaClasse = new MyClass;

   // attenzione al memory leak
}


Questa semplice linea di codice agisce sia sullo stack sia sull'heap. Infatti lo statement a sinistra dell'uguale definisce nello stack una variabile miaClasse di tipo puntatore a MyClass. Per quanto detto precedentemente, la variabile miaClasse essendo definita nello stack restera' valida fino all'uscita dallo scope corrente, ovvero nel nostro esempio, fino alla parentesi }. Da li' in avanti ci sara' impossile usare la variabile miaClasse.
Lo statement a destra dell'uguale richiama l'operatore new, ovvero viene allocata nell'heap una regione di memoria grande a sufficienza per contenere un oggetto di tipo MyClass. Essendo nell'heap, questa regione di memoria non andra' mai fuori scope fino al termine del programma e non potra' essere riciclata se non prima opportunamente liberata con l'uso dell'operatore delete.
Attenzione che nel momento che viene chiusa la parentesi graffa, miaClasse non e' piu' valida e noi non sapremo piu' rintracciare la regione di memoria allocata dall'operatore new. Questo fenomeno e' noto come memory leak ed e' una delle maggiori cause di perdita di prestazioni di un programma mal scritto. Infatti, non solo non saremo piu' in grado di utilizzare i valori contenuti nella regione di memoria puntata da miaClasse, ma non saremo nemmeno in grado di liberarla al termine dell'utilizzo.

Come possiamo evitare di sprecare memoria? Una risposta semplice non esiste, se volete, una risposta banale potrebbe essere: avere ben chiaro in mente chi e' il responsabile della memoria. Questo argomento va sicuramente approfondito, ma non adesso e non qui...

Rimanete in linea se volete saperne di piu'!

Chiunque può lasciare commenti su questo blog, ammesso che vengano rispettate due regole fondamentali: la buona educazione e il rispetto per gli altri.

Per commentare potete utilizzare diversi modi di autenticazione, da Google a Facebook e Twitter se non volete farvi un account su Disqus che resta sempre la nostra scelta consigliata.

Potete utilizzare tag HTML <b>, <i> e <a> per mettere in grassetto, in corsivo il testo ed inserire link ipertestuali come spiegato in questo tutorial. Per aggiungere un'immagine potete trascinarla dal vostro pc sopra lo spazio commenti.

A questo indirizzo trovate indicazioni su come ricevere notifiche via email sui nuovi commenti pubblicati.

0 commenti:

Posta un commento

Chiunque può lasciare commenti su questo blog, ammesso che vengano rispettate due regole fondamentali: la buona educazione e il rispetto per gli altri.

Per commentare potete utilizzare diversi modi di autenticazione, da Google a Facebook e Twitter se non volete farvi un account su Disqus che resta sempre la nostra scelta consigliata.

Potete utilizzare tag HTML <b>, <i> e <a> per mettere in grassetto, in corsivo il testo ed inserire link ipertestuali come spiegato in questo tutorial. Per aggiungere un'immagine potete trascinarla dal vostro pc sopra lo spazio commenti.

A questo indirizzo trovate indicazioni su come ricevere notifiche via email sui nuovi commenti pubblicati.

Related Posts Plugin for WordPress, Blogger...