Roep de functie "DoStackOverflow" een keer op vanaf jouw code en je krijgt de EStackOverflow fout veroorzaakt door Delphi met het bericht "stack overflow".
functie DoStackOverflow: geheel getal;
beginnen
resultaat: = 1 + DoStackOverflow;
einde;
Wat is deze "stapel" en waarom is er een overloop met de bovenstaande code?
Dus de DoStackOverflow-functie noemt zichzelf recursief - zonder een "exit-strategie" - het blijft maar draaien en verlaat het nooit.
Een snelle oplossing, zou u doen, is om de voor de hand liggende bug die u heeft op te heffen en ervoor te zorgen dat de functie op een gegeven moment bestaat (zodat uw code kan worden uitgevoerd vanaf waar u de functie hebt aangeroepen).
Je gaat verder en je kijkt nooit achterom, je geeft niet om de bug / uitzondering zoals deze nu is opgelost.
Toch blijft de vraag: wat is deze stapel en waarom is er een overloop?
Geheugen in uw Delphi-toepassingen
Wanneer u begint met programmeren in Delphi, kunt u een bug zoals hierboven ervaren, u zou het oplossen en verder gaan. Deze is gerelateerd aan geheugentoewijzing. Meestal geeft u niet om geheugentoewijzing zolang u
gratis wat je maakt.Naarmate je meer ervaring opdoet in Delphi, begin je met het maken van je eigen lessen, instantiseer ze, geef om geheugenbeheer en dergelijke.
Je komt op het punt waar je in de Help iets als dit leest "Lokale variabelen (gedeclareerd binnen procedures en functies) bevinden zich in die van een applicatie stapel." en ook Klassen zijn referentietypes, dus ze worden niet gekopieerd bij toewijzing, ze worden doorgegeven door middel van referentie en ze worden toegewezen aan de hoop.
Dus, wat is "stapel" en wat is "hoop"?
Stapel vs. Hoop
Uw applicatie uitvoeren op Windowszijn er drie gebieden in het geheugen waar uw toepassing gegevens opslaat: globaal geheugen, heap en stack.
Globale variabelen (hun waarden / gegevens) worden opgeslagen in het globale geheugen. Het geheugen voor globale variabelen wordt gereserveerd door uw applicatie wanneer het programma start en blijft toegewezen totdat uw programma eindigt. Het geheugen voor globale variabelen wordt "gegevenssegment" genoemd.
Aangezien het wereldwijde geheugen slechts eenmaal is toegewezen en vrijgegeven bij het beëindigen van het programma, geven we er in dit artikel niets om.
Bij stack en heap vindt dynamische geheugentoewijzing plaats: wanneer u een variabele voor een functie maakt, wanneer u een instantie van een klasse maakt wanneer u parameters naar een functie verzendt en het resultaat gebruikt / doorgeeft waarde.
Wat is Stack?
Wanneer u een variabele binnen een functie declareert, wordt het geheugen dat nodig is om de variabele vast te houden, toegewezen vanuit de stapel. U schrijft gewoon "var x: integer", gebruikt "x" in uw functie, en wanneer de functie wordt afgesloten, geeft u niets om geheugentoewijzing of vrijmaken. Wanneer de variabele buiten het bereik valt (code verlaat de functie), wordt het geheugen dat op de stapel is genomen, vrijgemaakt.
Het stapelgeheugen wordt dynamisch toegewezen met behulp van de LIFO-benadering ("last in first out").
In Delphi-programma's, wordt stapelgeheugen gebruikt door
- Lokale routine (methode, procedure, functie) variabelen.
- Routineparameters en retourtypen.
- Windows API-functie oproepen.
- Records (dit is de reden waarom u niet expliciet een instantie van een recordtype hoeft te maken).
U hoeft het geheugen op de stapel niet expliciet vrij te maken, omdat het geheugen automatisch voor u wordt toegewezen wanneer u bijvoorbeeld een lokale variabele voor een functie declareert. Wanneer de functie wordt afgesloten (soms zelfs eerder vanwege Delphi-compileroptimalisatie), wordt het geheugen voor de variabele automatisch magisch vrijgegeven.
Grootte geheugenstapel is standaard groot genoeg voor uw (zo complex als ze zijn) Delphi-programma's. De waarden voor "Maximale stapelgrootte" en "Minimale stapelgrootte" in de Linker-opties voor uw project specificeren standaardwaarden - in 99,99% hoeft u dit niet te wijzigen.
Beschouw een stapel als een stapel geheugenblokken. Wanneer u een lokale variabele declareert / gebruikt, zal Delphi-geheugenbeheerder het blok van boven kiezen, gebruiken en wanneer het niet langer nodig is, wordt het teruggebracht naar de stapel.
Als lokaal variabel geheugen uit de stapel wordt gebruikt, worden lokale variabelen niet geïnitialiseerd wanneer ze worden gedeclareerd. Verklaar een variabele "var x: integer" in een bepaalde functie en probeer de waarde te lezen wanneer u de functie invoert - x heeft een "vreemde" niet-nulwaarde. Dus initialiseer (of stel waarde) altijd in op uw lokale variabelen voordat u hun waarde leest.
Dankzij LIFO zijn stapelbewerkingen (geheugentoewijzing) snel omdat er slechts een paar bewerkingen (push, pop) nodig zijn om een stapel te beheren.
Wat is hoop?
Een heap is een geheugengebied waarin dynamisch toegewezen geheugen is opgeslagen. Wanneer u een instantie van een klasse maakt, wordt het geheugen toegewezen vanuit de heap.
In Delphi-programma's wordt heapgeheugen gebruikt door / wanneer
- Een instantie van een klasse maken.
- Dynamische arrays maken en vergroten of verkleinen.
- Geheugen expliciet toewijzen met GetMem, FreeMem, New en Dispose ().
- ANSI / wide / Unicode-strings, varianten, interfaces gebruiken (automatisch beheerd door Delphi).
Heapgeheugen heeft geen mooie lay-out waar er enige volgorde zou zijn bij het toewijzen van geheugenblokken. Hoop ziet eruit als een blikje knikkers. Geheugentoewijzing vanaf de heap is willekeurig, een blok hier vandaan dan een blok vanaf daar. Heap-bewerkingen zijn dus iets langzamer dan die op de stapel.
Wanneer u om een nieuw geheugenblok vraagt (d.w.z. een instantie van een klasse maken), zal Delphi Memory Manager dit voor u regelen: u krijgt een nieuw geheugenblok of een gebruikt en weggegooid blok.
De heap bestaat uit al het virtuele geheugen (RAM en schijfruimte).
Handmatig geheugen toewijzen
Nu alles over het geheugen duidelijk is, kunt u het bovenstaande (in de meeste gevallen) veilig negeren en gewoon doorgaan met het schrijven van Delphi-programma's zoals u gisteren deed.
U moet natuurlijk weten wanneer en hoe u handmatig geheugen kunt toewijzen / vrijmaken.
De "EStackOverflow" (vanaf het begin van het artikel) is verhoogd omdat bij elke aanroep van DoStackOverflow een nieuw segment geheugen is gebruikt vanuit de stapel en de stapel beperkingen heeft. Zo simpel is het.