Heap vs. Stalak za Delphi programere

Jednom se obratite funkciji "DoStackOverflow" svoj kod i dobit ćete EStackOverflow greška koju je Delphi podigao s porukom "stack overflow".


funkcija DoStackOverflow: cijeli broj;

početi

 rezultat: = 1 + DoStackOverflow;

kraj;

Što je to "stack" i zašto tamo postoji prelijevanje pomoću koda iznad?

Dakle, DoStackOverflow funkcija se rekurzivno poziva - bez „izlazne strategije“ - samo se nastavlja vrtjeti i nikad ne prestaje.

Brzo ispravljanje, to biste trebali učiniti je očistiti očiglednu pogrešku koju imate i osigurati da funkcija postoji u nekom trenutku (tako da vaš kôd može nastaviti izvršavati od mjesta na kojem ste pozvali funkciju).

Nastavite dalje i nikad se ne osvrćete unatrag, ne mareći za grešku / iznimku kao što je to sada riješeno.

Ipak, ostaje pitanje: što je ovaj stap i zašto postoji preljev?

Memorija u vašim Delphi aplikacijama

Kada započnete s programiranjem u Delphiju, može doći do pogreške poput ove, riješili biste je i krenite dalje. Ovaj se odnosi na dodjelu memorije. Većinu vremena se ne biste brinuli o raspodjeli memorije sve dok to niste

instagram viewer
oslobodite ono što vi stvorite.

Kako steknete više iskustva u Delphiju, započinjete kreirati vlastite časove, instancirati ih, brinuti se za upravljanje memorijom i slično.

Doći ćete do točke kad ćete u pomoći pročitati nešto poput "Lokalne varijable (deklarirane u postupcima i funkcijama) nalaze se u aplikaciji stog." I također Klase su referentne vrste, pa se pri zadatku ne kopiraju, prosljeđuju ih referencom i raspoređuju se na hrpa.

Dakle, što je "stack" i što je "heap"?

Stack vs. Hrpa

Pokretanje aplikacije u sustavu Windows, postoje tri područja u memoriji u kojima vaša aplikacija pohranjuje podatke: globalna memorija, heap i stack.

Globalne varijable (njihove vrijednosti / podaci) pohranjuju se u globalnu memoriju. Memorija za globalne varijable zadržava vaša aplikacija kada se program pokrene i ostaje mu dodijeljeno dok se program ne zaustavi. Memorija za globalne varijable naziva se "segment podataka".

Budući da se globalna memorija samo jednom dodjeljuje i oslobađa nakon završetka programa, to nas u ovom članku ne zanima.

Korak i hrpa su mjesta gdje se odvija dinamička raspodjela memorije: kada stvorite varijablu za funkciju, kad stvorite instancu klase kad parametre pošaljete funkciji i koristite / proslijedite njen rezultat vrijednost.

Što je stog?

Kad deklarirate varijablu unutar funkcije, memorija koja je potrebna za držanje varijable dodjeljuje se iz snopa. Jednostavno napišete "var x: integer", koristite "x" u svojoj funkciji, a kad funkcija izlazi, ne brinete o dodjeli memorije niti oslobađanju. Kad varijabla izađe iz okvira (kôd napušta funkciju), memorija koja je uzeta u stog oslobađa se.

Memorija snopa dodjeljuje se dinamički koristeći LIFO ("last in first out") pristup.

U Delphi programi, memoriju slaganja koristi

  • Lokalne rutinske (metoda, postupak, funkcija) varijable.
  • Rutinski parametri i vrste povratka.
  • Windows API funkcija poziva.
  • Zapisi (zato ne morate izričito stvoriti instancu vrste zapisa).

Ne morate izričito osloboditi memoriju na snopu jer je memorija automatski dodijeljena za vas kada, primjerice, deklarirate lokalnu varijablu za funkciju. Kad funkcija prestane (ponekad čak i prije zahvaljujući optimizaciji Delphi kompajlera), memorija za varijablu automatski će se magično osloboditi.

Veličina memorijske memorije prema defaultu je dovoljno velik za vaše (toliko složene) programe Delphi. Vrijednosti "Maksimalna veličina snopa" i "Minimalna veličina hrpe" na Linker opcijama za vaš projekt navode zadane vrijednosti - u 99,99% ne biste trebali mijenjati ovo.

Zamislite hrpu kao hrpu blokova memorije. Kad izjavite / upotrijebite lokalnu varijablu, Delphi upravitelj memorije će odabirati blok s vrha, upotrijebiti ga, a kada više ne treba vraća ga natrag u snop.

Upotrebljavajući lokalnu memoriju varijabli koja se koristi iz snopa, lokalne varijable se ne inicijaliziraju kada su deklarirane. Proglasite varijablu "var x: integer" u nekoj funkciji i pokušajte samo pročitati vrijednost kad uđete u funkciju - x će imati neku "čudnu" nultu vrijednost. Dakle, uvijek inicijalizirajte (ili postavite vrijednost) na svoje lokalne varijable prije nego što pročitate njihovu vrijednost.

Zbog LIFO operacije sloga (dodjele memorije) su brze jer je za upravljanje snopom potrebno samo nekoliko operacija (push, pop).

Što je heap?

Hrpa je područje memorije u koje se pohranjuje dinamički raspoređena memorija. Kada stvorite instancu klase, memorija se dodjeljuje iz gomile.

U Delphi programima heap memorija koristi / when

  • Izrada instancije klase.
  • Izrada i promjena veličine dinamičkih nizova.
  • Izričito raspoređivanje memorije pomoću GetMem, FreeMem, New i Dispose ().
  • Korištenje ANSI / wide / Unicode nizova, varijanti, sučelja (automatski upravlja Delphi).

Heap memorija nema lijep izgled tamo gdje bi bilo poretka je dodjela blokova memorije. Heap izgleda kao limenka od mramora. Dodjela memorije iz hrpe je slučajna, blok odavde nego blok odande. Dakle, operacije gomile su malo sporije od onih na snopu.

Kad tražite novi memorijski blok (tj. Stvorite instancu klase), Delphi upravitelj memorije će to riješiti za vas: dobit ćete novi memorijski blok ili iskorišteni i odbačeni.

Hrpa se sastoji od cjelokupne virtualne memorije (RAM-a i prostora na disku).

Ručno raspoređivanje memorije

Sad kad je sve o memoriji jasno, možete sigurno (u većini slučajeva) zanemariti gore navedeno i jednostavno nastaviti pisati Delphi programe kao što ste to radili jučer.

Naravno, trebali biste biti svjesni kada i kako ručno rasporediti / osloboditi memoriju.

Podignut je "EStackOverflow" (s početka članka), jer se svakim pozivom na DoStackOverflow novi segment memorije koristi iz snopa i snop ima ograničenja. Jednostavno.