Gestione della memoria in C++

La memoria di un processo in un sistema operativo è divisa in diverse aree o segmenti, ognuna delle quali ha uno scopo specifico. Le quattro principali aree di memoria in un processo sono:

Stack:

  • Lo stack è una regione di memoria utilizzata per la gestione delle chiamate di funzione e delle variabili locali.
  • Le variabili locali e i dati di controllo, come gli indirizzi di ritorno delle funzioni, vengono memorizzati nello stack.
  • L’allocazione e la deallocazione della memoria nello stack sono gestite automaticamente dal compilatore e dal sistema operativo.
  • Il formato di accesso dello stack è di tipo “last in, first out” (LIFO), il che significa che l’ultimo elemento inserito è il primo a essere rimosso.

Heap:

  • L’heap è una regione di memoria utilizzata per l’allocazione dinamica di dati a lungo termine.
  • In questa area, vengono allocate e deallocate strutture dati come gli oggetti o le strutture di dati complesse a cui si fa riferimento tramite puntatori.
  • La gestione della memoria nell’heap richiede una maggiore attenzione da parte del programmatore, poiché è necessario allocare e liberare la memoria manualmente per evitare perdite di memoria (memory leaks) o accessi errati.

Static:

  • L’area statica è destinata a variabili e dati statici.
  • Questa regione di memoria contiene variabili globali e variabili statiche locali, che vengono allocate una sola volta all’inizio dell’esecuzione del programma e mantengono il loro valore per tutto il ciclo di vita del processo.
  • L’accesso a queste variabili è possibile in qualsiasi momento durante l’esecuzione del programma.

Text o codice:

  • L’area text contiene il codice eseguibile del programma.
  • Questa parte della memoria contiene le istruzioni binarie del programma, e il sistema operativo non consente di scrivere direttamente in questa area. Quindi Il programmatore non ha accesso a questa parte della memoria
  • Le istruzioni vengono eseguite dalla CPU direttamente dalla memoria text.

alt text

Esempio

Prendiamo in considerazione il seguente pezzo di codice:

#include <iostream>
using namespace std;

int base = 7;

int potenza(int b, int e){
    int r = 1;
    for(int i=0; i<e; i++){
        r = r * b; // eseguo l'operazione di elevazione a potenza
    }
    return r; // restituisco il risultato
}

int main()
{
    int esponente;
    cin >> esponente;
    int risultato = potenza(base, esponente);
    cout << "Il risultato è: "<<risultato<<endl;

    return 0;
}

Capiamo ogni variabile in quale parte della memoria viene allocata:

  • Globale (statico o dati), contiene le variabili globali, ovvero quelle create all’esterno delle funzioni
    Nel caso in esempio c’è una sola variabile globale int base che è visibile ed utilizzabile in qualunque parte del programma. La sua dichiarazione infatti viene effettuata fuori dalle funzioni, all’inizio del codice.

  • Stack, contiene le variabili interne alle funzioni, compresi i parametri di queste.
    Nel caso in esempio ci sono 6 variabili allocate nello stack. In ordine di allocazione troviamo:

    • int esponente e int risultato create nel main
    • int b, int a, int r create nel momento in cui viene svolta la funzione potenza
    • int i che esiste solamente nell’intervallo di tempo nel quale viene svolto il ciclo for.
  • Heap, contiene le variabili create dinamicamente, in questo esempio di codice non viene utilizzata.

    Per “variabili create dinamicamente” si intendono variabili dichiarate dinamicamente, non assegnate dinamicamente.

  • Text, contiene il codice c++ convertito in linguaggio macchina. Un esempio potrebbe essere il seguente: