Stack overflow

Da Wikipedia, l'enciclopedia libera.

In informatica uno stack overflow avviene quando è richiesto l'uso di una quantità troppo elevata di memoria nello stack.

In molti linguaggi di programmazione lo 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 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, e tipicamente come conseguenza di questa situazione si verifica un crash del programma[1]. Questa classe di bug solitamente è causata da uno dei due tipi di errori di programmazione[2]: la ricorsione infinita e l'uso di variabili di stack molto grandi.

Ricorsione infinita[modifica | modifica wikitesto]

La causa più comune di uno stack overflow è una ricorsione con profondità eccessiva o infinita.

I linguaggi che implementano la tecnica tail recursion, come ad esempio il linguaggio Scheme, permettono una particolare ricorsione infinita che possa essere eseguita senza stack overflow. Questo avviene poiché le chiamate che fanno uso di tail-recursion non richiedono uno spazio aggiuntivo nello stack[3] .

Variabili di stack molto grandi[modifica | modifica wikitesto]

L'altra causa principale dello stack overflow è il tentativo di allocare più memoria nello stack di quella che è disponibile. Questo avviene tipicamente quando si crea un array di variabili locali molto grande. Per questo motivo gli array più grandi di qualche kilobyte dovrebbero essere allocati dinamicamente anziché allocarli come variabili locali[4].

Cause che possono ridurre la dimensione dello stack disponibile e quindi rendere più probabile uno stack overflow[modifica | modifica wikitesto]

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 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 ad un programma che non usi i thread.

Allo stesso modo, le persone che si avvicinano allo sviluppo di un kernel sono invitate a non usare algoritmi ricorsivi e buffer molto grandi nello stack[5][6].

Esempi nel linguaggio C/C++[modifica | modifica wikitesto]

Ricorsione infinita con una funzione[modifica | modifica wikitesto]

 void f() {
   f();
 }
 int main(void) {
   f();
   return 0;
 }

Questo frammento di codice invoca la funzione f(), e la funzione f() a sua volta richiama se stessa, generando in tal modo una ricorsione infinita.

Ricorsione infinita con due funzioni[modifica | modifica wikitesto]

 void f(void); 
 void g(void);
 
 int main(void) {
   f();
 
   return 0;
 }
 
 void f(void) {
   g();
 }
 
 void g(void) {
   f();  
 }

La funzione f() e la funzione g() si richiamano continuamente a vicenda, finché non si verifica lo stack overflow.

Variabile nello stack eccessivamente grande[modifica | modifica wikitesto]

 int main(void) {
   double n[10000000]; 
   return 0;
 }

L'array dichiarato in questo frammento di codice richiede più memoria di quella disponibile nello stack, causando così uno stack overflow.

Note[modifica | modifica wikitesto]

  1. ^ James Craig Burley, Using and Porting GNU Fortran, 1º giugno 1991.
  2. ^ Kalev Danny, Understanding Stack Overflow, 5 settembre 2000.
  3. ^ An Introduction to Scheme and its Implementation, 19 febbraio 1997.
  4. ^ Howard Feldman, Modern Memory Management, Part 2, 23 novembre 2005.
  5. ^ Kernel Programming Guide: Performance and Stability Tips, Apple Inc., 7 novembre 2006.
  6. ^ Randy Dunlap, Linux Kernel Development: Getting Started, 19 maggio 2005.

Voci correlate[modifica | modifica wikitesto]