Apelați funcția „DoStackOverflow” odată de la Codul tau și veți obține EStackOverflow eroare ridicată de Delphi cu mesajul „overflow stack”.
funcţie DoStackOverflow: număr întreg;
începe
rezultat: = 1 + DoStackOverflow;
Sfârșit;
Ce este această „stivă” și de ce există o revărsare acolo folosind codul de mai sus?
Deci, funcția DoStackOverflow se numește recursiv - fără o „strategie de ieșire” - ea continuă să se rotească și nu iese niciodată.
O soluție rapidă, ar face, este să ștergeți eroarea evidentă pe care o aveți și să vă asigurați că funcția există la un moment dat (astfel încât codul dvs. să poată continua să execute de unde ați apelat funcția).
Continuați și nu vă uitați niciodată înapoi, fără să vă preocupați de eroare / excepție, așa cum este acum rezolvată.
Cu toate acestea, rămâne întrebarea: ce este această stivă și de ce există un preaplin?
Memorie în aplicațiile dvs. Delphi
Când începeți programarea în Delphi, s-ar putea să întâmpinați o eroare ca cea de mai sus, o veți rezolva și continuați. Acesta este legat de alocarea memoriei. De cele mai multe ori nu ți-ar păsa de alocarea memoriei atâta timp cât tu
gratuit ce creați.Pe măsură ce câștigi mai multă experiență în Delphi, începi să-ți creezi propriile clase, să le instantanezi, să le pese de gestionarea memoriei și deopotrivă.
Veți ajunge la punctul în care veți citi, în ajutor, ceva de genul "Variabilele locale (declarate în proceduri și funcții) se află în aplicația grămadă." Si deasemenea Clasele sunt tipuri de referință, deci nu sunt copiate la atribuire, sunt trecute prin referință și sunt alocate pe morman.
Deci, ce este „stivă” și ce este „grămadă”?
Stack vs. Morman
Rulează aplicația pe Windows, există trei zone în memorie în care aplicația dvs. stochează date: memorie globală, acumulator și stivă.
Variabilele globale (valorile / datele lor) sunt stocate în memoria globală. Memoria pentru variabilele globale este rezervată de aplicația dvs. atunci când programul începe și rămâne alocat până la încheierea programului. Memoria pentru variabile globale se numește „segment de date”.
Deoarece memoria globală este alocată și eliberată o singură dată la terminarea programului, în acest articol nu ne pasă.
Stack și heap sunt locul în care are loc alocarea dinamică a memoriei: atunci când creați o variabilă pentru o funcție, când creați o instanță a unei clase când trimiteți parametrii unei funcții și utilizați / treceți rezultatul acesteia valoare.
Ce este Stack?
Când declarați o variabilă în interiorul unei funcții, memoria necesară pentru a ține variabila este alocată din stivă. Pur și simplu scrieți „var x: integer”, folosiți „x” în funcția dvs., iar când funcția iese, nu vă pasă de alocarea de memorie și nici de eliberarea. Când variabila iese din raza de acțiune (codul iese din funcție), memoria care a fost luată pe stivă este eliberată.
Memoria de stivă este alocată dinamic folosind abordarea LIFO („ultimul în primul ieșire”).
În Programe Delphi, memoria de stivă este folosită de
- Variabilele de rutină locală (metodă, procedură, funcție).
- Parametri de rutină și tipuri de retur.
- Funcția API Windows apeluri.
- Înregistrări (acesta este motivul pentru care nu trebuie să creați explicit o instanță de tip înregistrare).
Nu trebuie să eliberați explicit memoria din stivă, deoarece memoria este alocată automat pentru dvs. atunci când, de exemplu, declarați o variabilă locală unei funcții. Când funcția iese (uneori chiar înainte ca urmare a optimizării Delphi a compilatorului), memoria variabilei va fi eliberată automat.
Dimensiunea stivei de memorie implicit este suficient de mare pentru programele dvs. Delphi (cât de complexe sunt ele). Valorile „Dimensiunea maximă a stivei” și „Dimensiunea minimă a stivei” din opțiunile Linker pentru proiectul dvs. specifică valori implicite - în 99,99% nu va trebui să modificați acest lucru.
Gândiți-vă la o stivă ca la o grămadă de blocuri de memorie. Când declarați / utilizați o variabilă locală, managerul de memorie Delphi va alege blocul din partea de sus, îl va folosi și atunci când nu va mai fi nevoie, va fi returnat înapoi la stivă.
Având memoria variabilă locală folosită din stivă, variabilele locale nu sunt inițializate atunci când sunt declarate. Declarați o variabilă "var x: integer" într-o anumită funcție și încercați doar să citiți valoarea atunci când introduceți funcția - x va avea o valoare "ciudată" non-zero. Deci, inițializați întotdeauna (sau setați valoarea) la variabilele dvs. locale înainte de a le citi valoarea.
Datorită LIFO, operațiunile de stivuire (alocarea memoriei) sunt rapide, deoarece doar câteva operații (push, pop) sunt necesare pentru a gestiona o stivă.
Ce este Heap?
Un morman este o regiune a memoriei în care este stocată memoria alocată dinamic. Când creați o instanță a unei clase, memoria este alocată din grup.
În programele Delphi, memoria heap este folosită de / când
- Crearea unei instanțe a unei clase.
- Crearea și redimensionarea tablourilor dinamice.
- Alocarea explicită a memoriei folosind GetMem, FreeMem, New și Eliminați ().
- Folosind șiruri ANSI / wide / Unicode, variante, interfețe (gestionate automat de Delphi).
Memoria Heap nu are un aspect frumos în care ar exista o anumită ordine de alocare a blocurilor de memorie. Mormanul arată ca o cutie de marmură. Alocarea memoriei din grămadă este întâmplătoare, un bloc de aici decât un bloc de acolo. Astfel, operațiunile de montaj sunt puțin mai lente decât cele de pe stivă.
Când solicitați un nou bloc de memorie (de exemplu, creați o instanță a unei clase), managerul de memorie Delphi va gestiona acest lucru pentru dvs.: veți primi un bloc de memorie nou sau unul folosit și aruncat.
Mormanul este format din toată memoria virtuală (RAM și spațiu pe disc).
Alocarea manuală a memoriei
Acum că totul despre memoria este limpede, puteți ignora în siguranță (în majoritatea cazurilor) cele de mai sus și pur și simplu continuați să scrieți programe Delphi așa cum ați făcut ieri.
Desigur, ar trebui să știți când și cum să alocați manual / memoria liberă.
„EStackOverflow” (de la începutul articolului) a fost ridicat, deoarece cu fiecare apel către DoStackOverflow, un nou segment de memorie a fost utilizat din stivă și stiva are limitări. Simplu ca buna ziua.