Programmeringsspråkbøker forklarer at verdityper opprettes på stack, og referansetyper opprettes på heap, uten å forklare hva disse to tingene er. Jeg har ikke lest en klar forklaring på dette. Jeg forstår hva en stack er. Men,
Stabel: Stabel:**
Heap:
delete
, delete[]
eller free
.new
eller malloc
.Eksempel:
int foo()
{
char *pBuffer; //<--nothing allocated yet (excluding the pointer itself, which is allocated here on the stack).
bool b = true; // Allocated on the stack.
if(b)
{
//Create 500 bytes on the stack
char buffer[500];
//Create 500 bytes on the heap
pBuffer = new char[500];
}//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;
**Stakken Når du kaller en funksjon, legges argumentene til den funksjonen pluss noe annet overhead på stakken. Noe informasjon (for eksempel hvor du skal gå ved retur) lagres også der. Når du deklarerer en variabel inne i funksjonen din, blir den variabelen også allokert på stakken.
Deallokering av stakken er ganske enkelt fordi du alltid deallokerer i omvendt rekkefølge som du tildeler. Stack-ting legges til når du går inn i funksjoner, de tilsvarende dataene fjernes når du avslutter dem. Dette betyr at du har en tendens til å holde deg innenfor et lite område av stakken med mindre du kaller mange funksjoner som kaller mange andre funksjoner (eller oppretter en rekursiv løsning).
Haugen (heap) Heap er et generisk navn for hvor du legger dataene du oppretter på farten. Hvis du ikke vet hvor mange romskip programmet ditt skal opprette, vil du sannsynligvis bruke new (eller malloc eller tilsvarende) operatør for å opprette hvert romskip. Denne tildelingen kommer til å holde seg en stund, så det er sannsynlig at vi vil frigjøre ting i en annen rekkefølge enn vi opprettet dem.
Dermed er haugen langt mer kompleks, fordi det ender opp med å være regioner av minne som er ubrukt sammenflettet med biter som er - minnet blir fragmentert. Å finne ledig minne av den størrelsen du trenger er et vanskelig problem. Dette er grunnen til at haugen bør unngås (selv om den fortsatt ofte brukes).
Implementering Implementering av både stabelen og haugen er vanligvis ned til runtime / OS. Ofte lager spill og andre applikasjoner som er ytelseskritiske sine egne minneløsninger som tar en stor del av minnet fra bunken og deretter deler det ut internt for å unngå å stole på operativsystemet for minne.
Dette er bare praktisk hvis minnebruken din er ganske forskjellig fra normen - dvs. for spill der du laster et nivå i en stor operasjon og kan kaste hele partiet i en annen stor operasjon.
Fysisk plassering i minnet. Dette er mindre relevant enn du tror på grunn av en teknologi kalt Virtual Memory som får programmet til å tro at du har tilgang til en bestemt adresse der de fysiske dataene er et annet sted (til og med på harddisken!). Adressene du får for bunken er i økende rekkefølge etter hvert som anropstreet ditt blir dypere. Adressene til bunken er uforutsigbare (dvs. implementeringsspesifikke) og ærlig talt ikke viktige.
Stakken er en del av minnet som kan manipuleres via flere viktige assemblerinstruksjoner, for eksempel 'pop' (fjern og returner en verdi fra stakken) og 'push' (skyv en verdi til stakken), men også call (ring en subrutine - dette skyver adressen for å returnere til stakken) og return (retur fra en subrutine - dette spretter adressen av stakken og hopper til den). Det er minneområdet under stakkpekeren register, som kan stilles inn etter behov. Stakken brukes også til å sende argumenter til subrutiner, og også for å bevare verdiene i registre før du kaller subrutiner.
Heap er en del av minnet som er gitt til et program av operativsystemet, vanligvis gjennom et syscall som malloc. På moderne operativsystemer er dette minnet et sett med sider som bare den anropende prosessen har tilgang til.
Størrelsen på stakken bestemmes ved kjøretid, og vokser vanligvis ikke etter at programmet starter. I et C-program må bunken være stor nok til å holde hver variabel som er deklarert i hver funksjon. Bunken vil vokse dynamisk etter behov, men operativsystemet gjør til slutt anropet (det vil ofte vokse bunken med mer enn verdien som malloc ber om, slik at i det minste noen fremtidige mallocs ikke trenger å gå tilbake til kjernen for å få mer minne. Denne oppførselen kan ofte tilpasses)
Fordi du har tildelt stakken før du starter programmet, trenger du aldri å malloc før du kan bruke stakken, så det er en liten fordel der. I praksis er det veldig vanskelig å forutsi hva som vil være raskt og hva som vil være tregt i moderne operativsystemer som har virtuelle minneundersystemer, fordi hvordan sidene implementeres og hvor de lagres er en implementeringsdetalj.