Chiamare una volta la funzione "DoStackOverflow" il tuo codice e otterrai il EStackOverflow errore generato da Delphi con il messaggio "overflow dello stack".
funzione DoStackOverflow: intero;
inizio
risultato: = 1 + DoStackOverflow;
fine;
Cos'è questo "stack" e perché c'è un overflow lì usando il codice sopra?
Quindi, la funzione DoStackOverflow si chiama ricorsivamente, senza una "strategia di uscita", continua a girare e non esce mai.
Una soluzione rapida, potresti fare, è cancellare l'evidente bug che hai e assicurarti che la funzione esista ad un certo punto (in modo che il tuo codice possa continuare l'esecuzione da dove hai chiamato la funzione).
Continui e non ti guardi mai indietro, senza preoccuparti del bug / dell'eccezione poiché ora è risolto.
Tuttavia, la domanda rimane: cos'è questo stack e perché c'è un overflow?
Memoria nelle tue applicazioni Delphi
Quando inizi a programmare in Delphi, potresti riscontrare bug come quello sopra, risolverlo e andare avanti. Questo è legato all'allocazione della memoria. La maggior parte delle volte non ti interesserebbe l'allocazione della memoria finché tu
libera ciò che crei.Man mano che acquisisci più esperienza in Delphi, inizi a creare le tue lezioni, istanziarle, preoccuparti della gestione della memoria e simili.
Arriverete al punto in cui leggerete, nella Guida, qualcosa di simile "Le variabili locali (dichiarate all'interno di procedure e funzioni) risiedono in un'applicazione pila." e anche Le classi sono tipi di riferimento, quindi non vengono copiate durante l'assegnazione, vengono passate per riferimento e vengono allocate su mucchio.
Quindi, cos'è "stack" e cos'è "heap"?
Stack vs. Mucchio
Esecuzione dell'applicazione su Windows, ci sono tre aree nella memoria in cui l'applicazione memorizza i dati: memoria globale, heap e stack.
Le variabili globali (i loro valori / dati) sono archiviate nella memoria globale. La memoria per le variabili globali è riservata dall'applicazione all'avvio del programma e rimane allocata fino al termine del programma. La memoria per le variabili globali è chiamata "segmento di dati".
Poiché la memoria globale viene allocata e liberata solo una volta al termine del programma, in questo articolo non ci interessa.
Stack e heap sono dove avviene l'allocazione dinamica della memoria: quando crei una variabile per una funzione, quando si crea un'istanza di una classe quando si inviano parametri a una funzione e si utilizza / passa il suo risultato valore.
Che cos'è lo stack?
Quando si dichiara una variabile all'interno di una funzione, la memoria richiesta per contenere la variabile viene allocata dallo stack. Scrivi semplicemente "var x: integer", usa "x" nella tua funzione e quando la funzione termina, non ti preoccupi dell'allocazione della memoria né della liberazione. Quando la variabile esce dall'ambito (il codice esce dalla funzione), la memoria che è stata acquisita nello stack viene liberata.
La memoria dello stack viene allocata in modo dinamico utilizzando l'approccio LIFO ("last in first out").
Nel Programmi Delphi, la memoria dello stack è utilizzata da
- Variabili di routine locali (metodo, procedura, funzione).
- Parametri di routine e tipi di restituzione.
- Funzione API di Windows chiamate.
- Record (ecco perché non è necessario creare esplicitamente un'istanza di un tipo di record).
Non è necessario liberare esplicitamente la memoria nello stack, poiché la memoria viene allocata automaticamente per te quando, ad esempio, si dichiara una variabile locale a una funzione. Quando la funzione viene chiusa (a volte anche prima a causa dell'ottimizzazione del compilatore Delphi), la memoria per la variabile verrà liberata automaticamente.
Dimensione della memoria dello stack è, per impostazione predefinita, abbastanza grande per i tuoi programmi Delphi (per quanto complessi). I valori "Dimensione massima dello stack" e "Dimensione minima dello stack" nelle opzioni Linker per il tuo progetto specificano i valori predefiniti: nel 99,99% non è necessario modificarlo.
Pensa a una pila come a una pila di blocchi di memoria. Quando dichiari / usi una variabile locale, il gestore della memoria di Delphi sceglierà il blocco dall'alto, lo userà e, quando non sarà più necessario, tornerà nello stack.
Avendo la memoria delle variabili locali utilizzata dallo stack, le variabili locali non vengono inizializzate quando dichiarate. Dichiarare una variabile "var x: numero intero" in alcune funzioni e provare a leggere il valore quando si immette la funzione - x avrà un valore "strano" diverso da zero. Quindi, inizializza sempre (o imposta il valore) sulle variabili locali prima di leggerne il valore.
A causa di LIFO, le operazioni dello stack (allocazione della memoria) sono veloci poiché sono necessarie solo poche operazioni (push, pop) per gestire uno stack.
Che cos'è l'heap?
Un heap è una regione di memoria in cui è memorizzata la memoria allocata dinamicamente. Quando si crea un'istanza di una classe, la memoria viene allocata dall'heap.
Nei programmi Delphi, la memoria heap viene utilizzata da / when
- Creazione di un'istanza di una classe.
- Creazione e ridimensionamento di array dinamici.
- Allocazione esplicita della memoria tramite GetMem, FreeMem, New e Dispose ().
- Utilizzo di stringhe, varianti, interfacce ANSI / wide / Unicode (gestite automaticamente da Delphi).
La memoria dell'heap non ha un layout piacevole in cui ci sarebbe un po 'di ordine nell'allocare i blocchi di memoria. L'heap sembra una lattina di marmi. L'allocazione di memoria dall'heap è casuale, un blocco da qui rispetto a un blocco da lì. Pertanto, le operazioni di heap sono un po 'più lente di quelle sullo stack.
Quando chiedi un nuovo blocco di memoria (ovvero crea un'istanza di una classe), il gestore della memoria di Delphi lo gestirà per te: otterrai un nuovo blocco di memoria o uno usato e scartato.
L'heap è costituito da tutta la memoria virtuale (RAM e spazio su disco).
Allocazione manuale della memoria
Ora che tutto ciò che riguarda la memoria è chiaro, puoi tranquillamente (nella maggior parte dei casi) ignorare quanto sopra e continuare semplicemente a scrivere programmi Delphi come hai fatto ieri.
Naturalmente, dovresti essere consapevole di quando e come allocare / liberare memoria manualmente.
"EStackOverflow" (dall'inizio dell'articolo) è stato generato perché ad ogni chiamata a DoStackOverflow è stato utilizzato un nuovo segmento di memoria dallo stack e lo stack presenta limitazioni. Così semplice.