Stack overflow: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
Migliorato la pagina
 
(39 versioni intermedie di 27 utenti non mostrate)
Riga 1:
{{nota disambigua|il sito di Q&A omonimo|Stack Overflow (sito)|Stack Overflow}}
In [[informatica]], uno '''''stack overflow''''' avviene quando è richiesto l'uso di una quantità troppo elevata di [[Memoria (informatica)|memoria]] nello [[Allocazione dinamica della memoria|''stack'']].
 
In molti [[linguaggi di programmazione]], lo [[Call stack|stack delle chiamate]] contiene una quantità limitata di memoria, che viene fissata di solito all'avvio del programma. La dimensione dello stack dipende da molteplici fattori, inclusi il linguaggio di programmazione, l'[[Architettura (computer)|architettura]] della macchina, l'uso del ''[[multithreading]],'' e la disponibilità di memoria nel sistema. Quando vieneè usata troppa memoria nello ''stack'' si dice che avviene un ''[[Overflow aritmetico|overflow]]'', e tipicamente come conseguenza di questa situazione si verifica un [[Crash (informatica)|crash]] del programma<ref name="fortran1">{{Cita web|cognome=Burley|nome=James Craig|titolo=Using and Porting GNU Fortran|url=http://sunsite.ualberta.ca/Documentation/Gnu/gcc-2.95.2/html_node/g77_597.html|data=1º giugno 1991|urlmorto=sì|urlarchivio=https://www.webcitation.org/6BBbWyyAU?url=http://sunsite.ualberta.ca/Documentation/Gnu/gcc-2.95.2/html_node/g77_597.html|dataarchivio=5 ottobre 2012}}</ref>. Questa classe di [[bug]] solitamente è causata da uno dei due tipi di errori di programmazione<ref name="devx">{{citeCita web|cognome=Danny|nome=Kalev|titolo=Understanding Stack Overflow|url=http://www.devx.com/tips/Tip/14276|data=5 settembre 2000}}</ref>: la ricorsione infinita e l'uso di variabili di stack molto grandi.
| last = Burley
| first = James Craig
| title = Using and Porting GNU Fortran
| url= http://sunsite.ualberta.ca/Documentation/Gnu/gcc-2.95.2/html_node/g77_597.html
| date = 1991-06-01 }}</ref>. Questa classe di [[bug]] solitamente è causata da uno dei due tipi di errori di programmazione<ref name="devx">
{{cite web
| last = Danny
| first = Kalev
| title = Understanding Stack Overflow
| url=http://www.devx.com/tips/Tip/14276
| date = 2000-09-05 }}</ref>: la ricorsione infinita e l'uso di variabili di stack molto grandi.
 
== Ricorsione infinita ==
{{Vedi anche|Loop infinito}}
La causa più comune di uno stack overflow è uanuna [[ricorsione]] con profondità eccessiva o infinita.
 
I linguaggi che implementano la tecnica [[Algoritmo_ricorsivo#Eliminazione_della_ricorsione|''tail recursion'']], come ad esempio il linguaggio [[Scheme]], permettono una particolare ricorsione infinita che possapuò essere eseguita senza ''stack overflow''. Questo avviene poiché le chiamate che fanno uso di ''tail- recursion'' non richiedono uno spazio aggiuntivo nello ''stack''<ref name="tailRecur">{{citeCita web|titolo=An Introduction to Scheme and its Implementation|url=http://www.federated.com/~jim/schintro-v14/schintro_73.html|data=19 febbraio 1997|urlmorto=sì|urlarchivio=https://web.archive.org/web/20070810213035/http://www.federated.com/~jim/schintro-v14/schintro_73.html|dataarchivio=10 agosto 2007}}</ref>.
| title = An Introduction to Scheme and its Implementation
| url=http://www.federated.com/~jim/schintro-v14/schintro_73.html
| date = 1997-02-19 }} </ref>
.
 
== Variabili di stack molto grandi ==
L'altra causa principale dello ''stack overflow'' è il tentativo di allocare più memoria nello stack di quella chedisponibile ènello disponibilestack. Questo avviene tipicamente quando si crea un [[array]] di [[Variabile (informatica)#Visibilità di una variabile|variabili locali]] molto grande. Per questo motivo gli array più grandi di qualche [[kilobyte]] dovrebbero essere allocati [[allocazioneAllocazione dinamica della memoria|allocati dinamicamente]] anziché allocarli come variabili locali<ref name="onlamp">{{citeCita web|cognome=Feldman|nome=Howard|titolo=Modern Memory Management, Part 2|url=http://www.onlamp.com/pub/a/onlamp/2005/11/23/memory-management-2.html|data=23 novembre 2005|accesso=10 novembre 2009|dataarchivio=20 settembre 2012|urlarchivio=https://web.archive.org/web/20120920112622/http://onlamp.com/pub/a/onlamp/2005/11/23/memory-management-2.html|urlmorto=sì}}</ref>.
| last = Feldman
| first = Howard
| title = Modern Memory Management, Part 2
| url=http://www.onlamp.com/pub/a/onlamp/2005/11/23/memory-management-2.html
| date = 2005-11-23 }} </ref>.
 
== Cause che possono ridurre la dimensione dello stack disponibile e quindi rendere più probabile uno ''stack overflow'' ==
Gli ''stack overflow'' sono aggravati da qualsiasi cosa riduca la dimensione effettiva dello ''stack'' di un programma.
 
Ad esempio un programma che viene eseguito come ''[[Thread (informatica)|thread]]'' singolo potrebbe funzionare correttamente, ma se lo stesso programma vieneè eseguito con ''thread'' multipli si verifica un ''crash'' del programma. Ciò avviene, perché molti programmi che usano i ''thread'' hanno a disposizione uno ''stack'' più piccolo per ogni singolo ''thread'' rispetto ada un programma che non usiusa i ''thread''.
 
Allo stesso modo, chi studia lo [[sviluppo (informatica)|sviluppo]] di un [[kernel]] è invitato a non usare [[algoritmo ricorsivo|algoritmi ricorsivi]] e [[buffer]] molto grandi nello stack<ref name="apple1">{{Cita web|editore=[[Apple Inc]].|titolo=Kernel Programming Guide: Performance and Stability Tips|url=https://developer.apple.com/DOCUMENTATION/Darwin/Conceptual/KernelProgramming/style/chapter_5_section_5.html|data=7 novembre 2006|urlmorto=sì|urlarchivio=https://web.archive.org/web/20081207013401/http://developer.apple.com/DOCUMENTATION/Darwin/Conceptual/KernelProgramming/style/chapter_5_section_5.html|dataarchivio=7 dicembre 2008}}</ref><ref name="xenotime">{{Cita web|cognome=Dunlap|nome=Randy|titolo=Linux Kernel Development: Getting Started|url=http://www.xenotime.net/linux/mentor/linux-mentoring.pdf|data=19 maggio 2005|urlmorto=sì|urlarchivio=https://web.archive.org/web/20120227142532/http://www.xenotime.net/linux/mentor/linux-mentoring.pdf|dataarchivio=27 febbraio 2012}}</ref>.
Allo stesso modo, le persone che si avvicinano allo [[sviluppo (informatica)| sviluppo]] di un [[kernel]] sono invitate a non usare [[algoritmo ricorsivo|algoritmi ricorsivi]] e [[buffer]] molto grandi nello stack<ref name="apple1">{{cite web
| publisher= [[Apple Inc]].
| title = Kernel Programming Guide: Performance and Stability Tips
| url=http://developer.apple.com/DOCUMENTATION/Darwin/Conceptual/KernelProgramming/style/chapter_5_section_5.html
| date = 2006-11-07 }} </ref><ref name="xenotime">{{cite web
| last = Dunlap
| first = Randy
| title = Linux Kernel Development: Getting Started
| url=http://www.xenotime.net/linux/mentor/linux-mentoring.pdf
| date = 2005-05-19 }} </ref>.
 
== Esempi nel linguaggio C/C++ ==
=== Ricorsione infinita con una funzione ===
<syntaxhighlight lang="c" line="1" copy=1>
void f() {
f();
}
int main(void) {
f();
return 0;
}
</syntaxhighlight>
 
Questo frammento di codice invoca la [[funzione (informatica)|funzione]] <code>f()</code>, e la funzione <code>f()</code> a sua volta richiama se stessa, generando in tal modo una ricorsione infinita.
===Ricorsione infinita con una funzione===
<source lang="c">
void f() {
f();
}
int main(void) {
f();
return 0;
}
</source>
 
=== Ricorsione infinita con due funzioni (mutuale) ===
Questo frammento di codice invoca la funzione <code>f()</code>, e la funzione <code>f()</code> a sua volta richiama se stessa, generando in tal modo una ricorsione infinita.
<syntaxhighlight lang="c" line="1" copy=1>
void f(void);
void g(void);
 
voidint gmain(void) {
===Ricorsione infinita con due funzioni===
f();
<source lang="c">
 
void f(void);
return 0;
void g(void);
}
intvoid mainf(void) {
fg();
}
return 0;
}
void fg(void) {
gf();
}
</syntaxhighlight>
void g(void) {
f();
}
</source>
 
La funzione <code>f()</code> e la funzione <code>g()</code> si richiamano continuamente a vicenda, finché non si verifica lo ''stack overflow''.
 
=== Variabile nello stack eccessivamente grande ===
<sourcesyntaxhighlight lang="c" line="1" copy=1>
int main(void) {
double n[10000000];
return 0;
}
</syntaxhighlight>
</source>
 
L'array dichiarato in questo frammento di codice richiede più memoria di quella disponibile nello ''stack'', causando così uno ''stack overflow''.
 
== Note ==
<references />
 
== Voci correlate ==
* [[Heap overflow]]
* [[Buffer overflow]]
 
== Collegamenti esterni ==
[[en:Stack overflow]]
* {{FOLDOC||stack overflow}}
[[es:Desbordamiento de pila]]
 
[[fr:Dépassement de pile]]
{{Portale|informatica}}
[[ja:スタックオーバーフロー]]
[[pl:Przepełnienie stosu]]
 
[[Categoria:Gestione del software]]