In breve
Uno stack viene utilizzato per l'allocazione di memoria statica e un heap per l'allocazione di memoria dinamica, entrambi memorizzati nella RAM del computer.
In dettaglio
La pila
Lo stack è una struttura di dati "LIFO" (last in, first out), gestita e ottimizzata dalla CPU abbastanza da vicino. Ogni volta che una funzione dichiara una nuova variabile, viene "inserita" nello stack. Quindi ogni volta che una funzione esce, tutte le variabili inserite nello stack da quella funzione vengono liberate (vale a dire, vengono eliminate). Una volta liberata una variabile di stack, quella regione di memoria diventa disponibile per altre variabili di stack.
Il vantaggio di utilizzare lo stack per memorizzare le variabili è che la memoria è gestita per te. Non è necessario allocare memoria manualmente o liberarla quando non è più necessaria. Inoltre, poiché la CPU organizza la memoria dello stack in modo così efficiente, leggere e scrivere sulle variabili dello stack è molto veloce.
Altro può essere trovato qui .
The Heap
L'heap è un'area della memoria del tuo computer che non è gestita automaticamente per te e non è gestita in modo così stretto dalla CPU. È una regione di memoria più fluttuante (ed è più grande). Per allocare memoria sull'heap, è necessario utilizzare malloc () o calloc (), che sono funzioni C integrate. Dopo aver allocato memoria nell'heap, sei responsabile dell'utilizzo di free () per deallocare tale memoria quando non ti serve più.
In caso contrario, il programma avrà quella che è nota come perdita di memoria. Cioè, la memoria sull'heap verrà comunque messa da parte (e non sarà disponibile per altri processi). Come vedremo nella sezione debug, esiste uno strumento chiamato Valgrind che può aiutarti a rilevare perdite di memoria.
A differenza dello stack, l'heap non ha limiti di dimensione per dimensioni variabili (a parte le ovvie limitazioni fisiche del computer). La memoria dell'heap è leggermente più lenta da leggere e da scrivere, poiché è necessario utilizzare i puntatori per accedere alla memoria dell'heap. Parleremo di puntatori a breve.
A differenza dello stack, le variabili create sull'heap sono accessibili da qualsiasi funzione, ovunque nel programma. Le variabili heap hanno essenzialmente portata globale.
Altro può essere trovato qui .
Le variabili allocate nello stack vengono archiviate direttamente nella memoria e l'accesso a questa memoria è molto veloce e la sua allocazione viene gestita al momento della compilazione del programma. Quando una funzione o un metodo chiama un'altra funzione che a sua volta chiama un'altra funzione, ecc., L'esecuzione di tutte quelle funzioni rimane sospesa fino a quando l'ultima funzione non ne restituisce il valore. Lo stack è sempre riservato in un ordine LIFO, l'ultimo blocco riservato è sempre il blocco successivo da liberare. Questo rende davvero semplice tenere traccia dello stack, liberare un blocco dallo stack non è altro che regolare un puntatore.
Le variabili allocate sull'heap hanno la memoria allocata in fase di esecuzione e l'accesso a questa memoria è un po 'più lento, ma la dimensione dell'heap è limitata solo dalla dimensione della memoria virtuale. Gli elementi dell'heap non hanno dipendenze tra loro e sono sempre accessibili in modo casuale in qualsiasi momento. È possibile allocare un blocco in qualsiasi momento e liberarlo in qualsiasi momento. Ciò rende molto più complesso tenere traccia di quali parti dell'heap sono allocate o libere in un dato momento.
Puoi usare lo stack se sai esattamente quanti dati devi allocare prima del tempo di compilazione e non sono troppo grandi. È possibile utilizzare l'heap se non si conosce esattamente la quantità di dati necessari in fase di esecuzione o se è necessario allocare molti dati.
In una situazione multi-thread, ogni thread avrà il proprio stack completamente indipendente, ma condividerà l'heap. Lo stack è specifico del thread e l'heap è specifico dell'applicazione. Lo stack è importante da considerare nella gestione delle eccezioni e nelle esecuzioni dei thread.
Ogni thread ottiene uno stack, mentre in genere esiste un solo heap per l'applicazione (anche se non è raro avere più heap per diversi tipi di allocazione).
In fase di esecuzione, se l'applicazione necessita di più heap, può allocare memoria dalla memoria libera e se lo stack necessita di memoria, può allocare memoria dalla memoria allocata memoria libera per l'applicazione.
Anche più dettagli sono forniti qui e qui .
Ora vieni alle risposte alla tua domanda .
In che misura sono controllati dal sistema operativo o dal runtime della lingua?
Il sistema operativo alloca lo stack per ogni thread a livello di sistema quando viene creato il thread. In genere il sistema operativo viene chiamato dal runtime della lingua per allocare l'heap per l'applicazione.
Altro può essere trovato qui .
Qual è il loro scopo?
Già dato in cima.
"Puoi usare lo stack se sai esattamente quanti dati devi allocare prima del tempo di compilazione, e non è troppo grande. Puoi usare l'heap se non sai esattamente quanti dati ti occorreranno in fase di esecuzione o se devi allocare molti dati ".
Altro può essere trovato qui .
Cosa determina la dimensione di ciascuno di essi?
La dimensione dello stack viene impostata dal sistema operativo quando viene creato un thread. La dimensione dell'heap viene impostata all'avvio dell'applicazione, ma può aumentare in base allo spazio necessario (l'allocatore richiede più memoria dal sistema operativo).
Cosa rende uno più veloce?
L'allocazione dello stack è molto più veloce poiché tutto ciò che fa è spostare il puntatore dello stack. Utilizzando i pool di memoria, è possibile ottenere prestazioni comparabili dall'allocazione dell'heap, ma ciò comporta una leggera complessità aggiuntiva e il suo mal di testa.
Inoltre, stack vs. heap non è solo una considerazione delle prestazioni; ti dice anche molto sulla durata prevista degli oggetti.
I dettagli possono essere trovati da qui .