Hunnik vs. Stack Delphi arendajate jaoks

Kutsuge funktsioon "DoStackOverflow" üks kord alates teie kood ja saate EStackOverflow Delphi tõstatatud viga teatega "virna ülevool".


funktsiooni DoStackOverflow: täisarv;

alustada

 tulemus: = 1 + DoStackOverflow;

lõpp;

Mis see "virn" on ja miks ülaltoodud koodi kasutades on seal ülevool?

Seega, DoStackOverflow funktsioon kutsub end rekursiivselt ise - ilma "väljumisstrateegiata" - see lihtsalt pöörleb ja ei välju kunagi.

Kiirparandus oleks teie tehtud ilmse vea kustutamine ja funktsiooni mingil hetkel olemasolu olemasolu (nii et teie kood saaks jätkata täitmist kohast, kuhu funktsiooni kutsusite).

Liigute edasi ega vaata kunagi tagasi, mitte ei hoolitse veast / erandist, nagu see on nüüd lahendatud.

Kuid küsimus jääb: mis see virn on ja miks on tekkinud ülevool?

Mälu teie Delphi rakendustes

Delfis programmeerimist alustades võib ilmneda selline viga nagu ülal, lahendaksite selle ja läheksite edasi. See on seotud mälu eraldamisega. Enamasti ei hooliks te nii pikalt mälu jaotamisest tasuta mida loote.

instagram viewer

Delphis rohkem kogemusi omandades alustate oma klasside loomist, juhendate neid, hoolite mäluhaldusest ja muust.

Jõuate punktini, kus loete spikrist midagi sellist "Kohalikud muutujad (deklareeritud protseduuride ja funktsioonide piires) asuvad rakenduses virna." ja ka Klassid on viitetüübid, seega neid ei loovutamisel kopeerita, need antakse edasi viitega ja nad eraldatakse klassis hunnik.

Mis on "stäkk" ja mis on "hunnik"?

Stack vs. Hunnik

Rakenduse käitamine Windowsis, on mälus kolm ala, kuhu teie rakendus andmeid salvestab: globaalne mälu, kuhja ja pinu.

Globaalsed muutujad (nende väärtused / andmed) salvestatakse globaalsesse mällu. Globaalsete muutujate mälu reserveerib teie rakendus programmi käivitamisel ja sellele eraldatakse kuni programmi lõppemiseni. Globaalsete muutujate mälu nimetatakse andmesegmendiks.

Kuna globaalne mälu eraldatakse ja vabastatakse programmi lõppedes ainult üks kord, ei huvita see meid selles artiklis.

Stack ja hunnik on koht, kus toimub dünaamiline mälujaotus: kui loote funktsiooni muutuja, kui loote klassi eksemplari, kui saadate funktsioonile parameetreid ja kasutate / edastate selle tulemuse väärtus.

Mis on pinu?

Muutuja deklareerimisel funktsioonis eraldatakse muutuja hoidmiseks vajalik mälu virnast. Kirjutate lihtsalt "var x: integer", kasutate "x" oma funktsioonis ja kui funktsioon väljub, ei hooli te mälu eraldamisest ega vabastamisest. Kui muutuja väljub ulatusest (kood väljub funktsioonist), vabastatakse virna võetud mälu.

Pinu mälu jaotatakse dünaamiliselt, kasutades lähenemisviisi LIFO ("viimane sisse esimesena").

Sisse Delphi programmid, pinu mälu kasutab

  • Lokaalse rutiini (meetod, protseduur, funktsioon) muutujad.
  • Rutiinsed parameetrid ja tagastamise tüübid.
  • Windowsi API funktsioon kutsub.
  • Kirjed (see ei ole põhjus, miks te ei pea konkreetselt looma kirje tüübi eksemplari).

Te ei pea virnas olevat mälu otseselt vabastama, kuna mälu eraldatakse teile automaatselt võluväel, kui deklareerite näiteks funktsiooni kohaliku muutuja. Kui funktsioon väljub (mõnikord isegi enne Delphi kompilaatori optimeerimist), vabastatakse muutuja mälu automaatselt maagiliselt.

Vormi mälu suurus on vaikimisi piisavalt suur teie (nii keerukate kui ka) Delphi programmide jaoks. Projekti Linkeri suvandites "Maksimaalne virna suurus" ja "Minimaalne virna suurus" täpsustatakse vaikeväärtused - 99,99% -l ei peaks te seda muutma.

Mõelge virna kui mäluplokkide kuhja. Kohaliku muutuja deklareerimisel / kasutamisel valib Delphi mäluhaldur ploki ülalt, kasutab seda ja kui seda enam ei vajata, tagastatakse see pinu tagasi.

Kui virnast kasutatakse kohalikku muutujamälu, siis kohalikke muutujaid ei deklareerita. Kuulutage mõnes funktsioonis muutuja "var x: täisarv" ja proovige funktsiooni sisestades lihtsalt väärtust lugeda - x-il on mingi "imelik" nullist erinev väärtus. Nii et enne nende väärtuse lugemist lähtestage (või määrake väärtus) alati kohalikele muutujatele.

Tänu LIFO-le on virna (mälu eraldamine) toimingud kiired, kuna virna haldamiseks on vaja ainult mõnda toimingut (tõuke-, hüpik- ja hüpiknupp).

Mis on hunnik?

Hunnik on mälu piirkond, kuhu salvestatakse dünaamiliselt eraldatud mälu. Klassi eksemplari loomisel eraldatakse mälu kuhjaga.

Delphi programmides kasutab hunnikmälu aeg / millal

  • Klassi eksemplari loomine.
  • Dünaamiliste massiivide loomine ja suuruse muutmine.
  • Mälu otsene eraldamine, kasutades rakendusi GetMem, FreeMem, New ja Dispose ().
  • Kasutades ANSI / laiad / Unicode stringe, variante, liideseid (haldab automaatselt Delphi).

Kogumälul pole kena paigutust, kus oleks mingi järjekord mäluplokkide eraldamiseks. Hunnik näeb välja nagu marmorist purk. Mälu jaotus kuhjast on juhuslik, plokk siit kui plokk sealt. Seega on hunniku toimingud natuke aeglasemad kui virnal.

Kui palute uut mäluplokki (st luua klassi eksemplari), tegeleb Delphi mäluhaldur selle eest teiega: saate uue või kasutatud ja kasutuselt kõrvaldatud mäluploki.

Hunnik koosneb kogu virtuaalsest mälust (RAM ja kettaruum).

Mälu käsitsi eraldamine

Nüüd, kui mäluga on kõik selge, võite ohutult (enamikul juhtudel) ülaltoodut ignoreerida ja jätkata Delphi programmide kirjutamist lihtsalt nagu eile.

Muidugi peaksite olema teadlik, millal ja kuidas mälu käsitsi eraldada / vabastada.

EStackOverflow (artikli algusest) tõsteti üles, kuna iga DoStackOverflow kõnega on virnast kasutatud uut mälusegmenti ja pinu on piiratud. Nii lihtne see ongi.

instagram story viewer