Storia della questione:
La memoria dello stack è presente in tutte le architetture principali. Nel linguaggio C, le variabili automatiche (locali) sono allocate nello stack, garantendo un'elevata velocità di allocazione e liberazione della memoria rispetto all'heap dinamico.
Problema:
L'uso dello stack è limitato in dimensione, le variabili automatiche vengono automaticamente distrutte dopo l'uscita dal blocco e il superamento dei limiti dello stack (stack overflow) porta a un'interruzione anomala del programma o alla corruzione dei dati.
Soluzione:
Le variabili locali dichiarate all'interno delle funzioni senza un modificatore speciale sono allocate nello stack. Quest'area di archiviazione automatica viene creata all'ingresso nella funzione e distrutta all'uscita. La dimensione dello stack è limitata e può essere modificata solo tramite opzioni di linking/sistema.
Esempio di codice:
#include <stdio.h> void foo() { int arr[100]; // allocato nello stack for (int i = 0; i < 100; ++i) arr[i] = i; printf("Primo elemento: %d ", arr[0]); } // arr viene distrutto dopo l'uscita da foo
Caratteristiche chiave:
È possibile restituire una variabile locale da una funzione per indirizzo?
No, perché la variabile viene distrutta dopo l'uscita dalla funzione, e il risultante "puntatore pendente" porta a comportamenti indefiniti.
int* bad() { int x = 42; return &x; // errore: il puntatore restituito punta a uno stack liberato }
È possibile allocare un grande array (ad esempio, 1 MB) nello stack?
Per la maggior parte dei sistemi, lo stack è limitato (da decine a centinaia di KB). Tentare di dichiarare enormi array nello stack porterà a uno stack overflow.
Qual è la differenza tra variabili statiche e automatiche per quanto riguarda l'allocazione?
Le variabili statiche (anche all'interno di una funzione) sono allocate nell'area di memoria statica, non vengono distrutte tra le chiamate, mentre quelle automatiche sono nello stack e vengono distrutte all'uscita dal blocco.
In una funzione per calcoli, è stato allocato un array 8192*1024 double nello stack. Il programma ha ricevuto SIGSEGV all'avvio su Linux, anche se compilato senza errori.
Vantaggi:
Svantaggi:
Per lavorare con grandi buffer sono stati utilizzati l'allocazione dinamica di memoria tramite malloc/free. Solo piccole variabili di lavoro sono state allocate nello stack.
Vantaggi:
Svantaggi: