Call stack: differenze tra le versioni
Contenuto cancellato Contenuto aggiunto
m Sostituito l'immagine relativa all'esempio di una call stack con la relativa versione SVG nell'introduzione |
|||
(37 versioni intermedie di 28 utenti non mostrate) | |||
Riga 1:
{{F|programmazione|febbraio 2013}}
[[File:Call stack layout.svg|thumb|Esempio]]
In [[informatica]], un '''''call stack''''' (traducibile letteralmente dall'[[Lingua inglese|inglese]] come "pila delle chiamate") è una zona di memoria di un programma, organizzata in forma di [[Pila (informatica)|stack]], nella quale sono immagazzinate le informazioni sulle ''[[subroutine]]'' attive in un dato momento (le ''subroutine'' attive sono quelle che sono state invocate ma la cui esecuzione non è terminata). Può essere tradotto come stack delle invocazioni a funzione (o chiamate a funzione) o stack delle invocazioni a metodo (o chiamate a metodo) a seconda del tipo di ''subroutine'' coinvolto.
Questo tipo di pila è spesso chiamato anche '''execution stack''', '''control stack''', '''function stack''', o '''run-time stack''', oppure, quando non vi è possibilità di confusione, semplicemente '''stack'''.
Una call stack può essere usata per molti scopi, ma la ragione principale per usarla è tenere traccia dei punti in cui ogni subroutine attiva dovrebbe restituire il controllo quando termina l'esecuzione. Se, per esempio, una subroutine DrawSquare (disegna un quadrato) chiama la subroutine DrawLine (disegna una linea) da quattro diversi punti, il codice di DrawLine deve poter conoscere a quale punto tornare terminata l'esecuzione. Questo compito è svolto tipicamente dal codice per ogni chiamata all'interno di DrawSquare inserendo l'indirizzo dell'[[istruzione]] dopo una particolare dichiarazione di chiamata ("return address" o indirizzo di ritorno) all'interno del call stack.▼
L'insieme delle informazioni specifiche di una ''subroutine'' all'interno di un ''call stack'' è detto ''frame''.
Poiché il call stack è organizzato come una pila, la [[Funzione (informatica)|funzione]] chiamante mette l'indirizzo di ritorno sopra la pila e la subroutine chiamata, quando termina, toglie l'indirizzo di ritorno dalla pila e trasferisce il controllo a quell'indirizzo. Se una subroutine chiamata chiama un'altra subroutine, essa metterà l'indirizzo di ritorno sopra la call stack e così via le informazioni vengono accatastate e rimosse come previsto dal [[programma (informatica)|programma]]. Se viene usato tutto lo spazio a disposizione del call stack, si verifica un errore chiamato [[stack overflow]]. Aggiungere una subroutine nel call stack è definito [[winding]]; toglierla è definito unwinding.▼
== Funzionamento ==
C'è solitamente solo un call stack associato con un [[programma (informatica)|programma]] in esecuzione (o più precisamente con ogni [[task]] o [[thread]] di un processo), tuttavia stack aggiuntivi possono essere creati per gestire [[segnale|segnali]] o per il [[multitasking]] cooperativo. Poiché ne esiste uno solo in questo importante contesto, ci si riferisce semplicemente allo stack (implicitamente "del task").▼
▲
▲Poiché il ''call stack'' è organizzato come una pila, la [[Funzione (informatica)|funzione]] chiamante mette l'indirizzo di ritorno sopra la pila e la ''subroutine'' chiamata, quando termina, toglie l'indirizzo di ritorno dalla pila e trasferisce il controllo a quell'indirizzo. Se una ''subroutine'' chiamata chiama un'altra ''subroutine'', essa metterà l'indirizzo di ritorno sopra la ''call stack'' e così via le informazioni vengono accatastate e rimosse come previsto dal [[programma (informatica)|programma]]. Se viene usato tutto lo spazio a disposizione del ''call stack'', si verifica un errore chiamato [[stack overflow]]. Aggiungere una ''subroutine'' nel ''call stack'' è definito
Nei [[linguaggio di programmazione|linguaggi di programmazione]] di alto livello, le specifiche del call stack sono nascoste solitamente dal [[programmatore]]. Egli fornisce accesso solo alla lista delle funzioni e non alla memoria dello stack stesso. Molti linguaggi [[Assembly]] d'altra parte, richiedono ai programmatori di essere coinvolti nella gestione dello stack. I dettagli dello stack in un linguaggio di programmazione dipendono anche dal compilatore, dal sistema operativo e dalle istruzioni disponibili.▼
▲C'è solitamente solo un ''call stack'' associato con un [[programma (informatica)|programma]] in esecuzione (o più precisamente con ogni [[task]] o [[thread (informatica)|thread]] di un processo), tuttavia stack aggiuntivi possono essere creati per gestire [[segnale (informatica)|segnali]] o per il [[multitasking]] cooperativo. Poiché ne esiste uno solo in questo importante contesto, ci si riferisce semplicemente allo stack (implicitamente "del task").
== Scopi del call stack ==▼
Lo scopo primario del call stack è:▼
▲Nei [[linguaggio di programmazione|linguaggi di programmazione]] di alto livello, le specifiche del ''call stack'' sono nascoste
* '''immagazzinare gli indirizzi di ritorno''' - Quando una subroutine viene chiamata, l'indirizzo dell'istruzione di ritorno deve essere salvato da qualche parte. Utilizzando una pila per salvare gli indirizzi di ritorno si hanno importanti vantaggi rispetto alle alternative. Uno di questi è che ogni task ha il proprio stack e pertanto le subroutine possono essere "rientranti" e quindi possono essere attive simultaneamente per task diversi che fanno cose diverse. Un altro vantaggio è che la [[ricorsione]] è automaticamente supportata. Quando una funzione chiama sé stessa ricorsivamente, un indirizzo di ritorno necessita di essere registrato per ogni attivazione della funzione così da poter essere usato per il ritorno da ogni attivazione della funzione. Questa capacità è automatica con un stack.▼
▲== Scopi del call stack ==
Un call stack può avere scopi aggiuntivi, dipendenti dal linguaggio, dal sistema operativo e dall'ambiente della macchina. Tra questi:▼
▲Lo scopo primario del ''call stack'' è:
▲*
* '''immagazzinare dati locali''' - Una subroutine frequentemente necessita di spazio di memoria per registrare i valori delle variabili locali, le variabili usate solo nella subroutine attiva e che non devono trattenere valori dopo il ritorno (alla funzione chiamante). È spesso conveniente per allocare spazio per questo uso spostarsi semplicemente in cima allo stack in modo sufficiente ad avere lo spazio. È molto veloce paragonato, ad esempio, con l'allocazione di tipo [[Allocazione_dinamica_della_memoria|heap]]. Ogni diversa attivazione di una subroutine ha il proprio spazio separato nello stack per i dati locali.▼
* '''passaggio di parametri''' - Le subroutine spesso richiedono che i valori dei parametri siano forniti dal codice che le chiama e non è raro che lo spazio per questi parametri possa essere nel call stack. Generalmente se ci sono solo pochi piccoli parametri, i registri del [[processore]], possono essere usati per il passaggio dei valori, ma se ci sono più parametri da gestire in questo modo, è necessario spazio in memoria. Il call stack lavora meglio come posto per questi parametri, specialmente poiché ogni chiamata della subroutine, che avrà diversi valori dei parametri, avrà uno spazio separato nel call stack per questi valori.▼
* '''stack di valutazione''' - Gli [[operandi]] per operazioni aritmetiche e logiche sono spesso inseriti nel [[registro]] e utilizzati là. Comunque, in alcune situazioni gli operandi possono essere accatastati ad una profondità arbitraria, il che significa che deve essere usato qualcosa di più del registro. Lo stack di questi operandi, similmente ai calcolatori di tipo RPN, è chiamato stack di valutazione (evaluation stack) e può occupare spazio nel call stack.▼
* '''puntatore dell'istanza corrente''' - Alcuni linguaggi orientati agli oggetti (come [[C++]]), immagazzinano questo puntatore come argomento delle funzioni nel call stack quando invocano un metodo. Questo puntatore punta all'istanza dell'oggetto a cui è associato il metodo invocato. È una parte essenziale del contesto di esecuzione di linguaggi orientati agli oggeti, poiché fornisce accesso ai dati posseduti dall'oggetto corrente. Questo puntatore è collegato a livelli utilizzati nella programmazione orientata agli oggetti con livelli (tipi di strutture stack) della run-time call stack.▼
▲Un ''call stack'' può avere scopi aggiuntivi, dipendenti dal linguaggio, dal sistema operativo e dall'ambiente della macchina. Tra questi:
* '''Ambiente dei contenitori di subroutines''' - Alcuni linguaggi di programmazione (come [[Pascal (programmazione)|Pascal]] e [[Ada (programmazione)|Ada]]) supportano [[Funzioni annidate|subroutines annidate]], permettendo ad una routine interna di accedere al contesto della sua routine contenitore, cioè' ai parametri e alle variabili locali nell'ambiente della routine esterna. Tali lingue generalmente permettono alle routines di effettuare chiamate ricorsive (la funzione richiama se stessa), ottenendo multiple call stacks per le chiamate di routines delle routines interne, ciascuna delle quali punta sullo stesso ambiente della routine esterna. Questo tipo di call frame è anche conosciuto come ''display''.▼
▲*
▲*
▲*
▲*
▲*
== Voci correlate ==
* [[
* [[Subroutine]]
* [[Allocazione dinamica della memoria]]
* [[Stack trace]]
{{Portale|
[[Categoria:Gestione della memoria]]
|