[MUSIC SPILLE]
>> DOUG LLOYD: OK så et forslag før du starter her.
Hvis du ikke har sett videoen på tips du kanskje ønsker å gjøre det først.
Fordi denne videoen er en annen måte å arbeide med pekere.
>> Så det kommer til å snakke om noen begreper
at vi dekker i pekere video, og vi er
kommer til å glatte over dem nå, forutsatt at de er allerede
liksom forstått.
Så det er bare din rettferdig advarsel at hvis du ser denne videoen
og du har ikke sett den pekere video, det kan liksom
fly over hodet ditt litt.
Og så kan det være bedre å se det i den rekkefølgen.
>> Så vi har allerede sett en måte å arbeide med pekere,
som er vi erklære en variabel, og da er vi
erklærer en annen variabel, en peker variabel, påpeker at til det.
Derfor har vi laget en variabel med et navn, vi har
opprettet en ekstra variabel med et navn, og vi påpeke at andre variable
på det første.
Denne typen har en problem, fordi det
krever at vi vet nøyaktig hvor mye minne vi er
kommer til å trenge i øyeblikket Vårt program er kompilert.
>> Hvorfor det?
Fordi vi må være i stand til å navngi eller identifisere alle de mulige varianter
vi kan støte på.
Vi kan ha en matrise som kan være stand til å holde mye informasjon,
men det er fortsatt ikke akkurat presise nok.
Hva om vi ikke vet, hva om vi har ingen anelse
hvor mye vi trenger ved kompilering?
Eller hva om vårt program vil kjøre for en veldig lang tid,
akseptere ulike bruker data, og vi kan egentlig ikke
anslå om vi er kommer til å trenge 1.000 enheter?
>> Det er ikke som vi kan si på kommandolinjen
angir hvor mange elementer du tror du trenger.
Vel hva om at gjetning er galt?
Dynamisk minne allokering slags tillater oss veien
å komme rundt dette problemet.
Og måten den gjør det er ved hjelp av pekere.
>> Vi kan bruke pekere til få tilgang til dynamisk
allokert minne, minne som er disponeres som programmet kjører.
Det er ikke avsatt ved kompilering.
Når du dynamisk tildele minne det kommer fra en pool
minne som kalles haugen.
Tidligere alt minnet vi har jobbet med i løpet
har kommet fra en pool minne som kalles stabelen.
En god måte å generelt holde mind-- og denne regelen
ikke alltid holder sant, men ganske mye nesten
alltid holder true-- er at enhver gang du gir en variabel name it
lever sannsynligvis på stakken.
Og når du ikke gjør det gi en variabel et navn,
som du kan gjøre med dynamisk minne tildeling, det lever på haugen.
>> Nå er jeg litt å presentere dette som hvis det er disse to bassenger minne.
Men du kan ha sett dette diagram, som vanligvis
en representasjon av hva minnet ser ut,
og vi ikke kommer til å bry seg om alt ting på toppen og bunnen.
Hva vi bryr oss om er denne delen i midten her, heap og stakk.
Som du kan se av ser på dette diagrammet,
disse faktisk er ikke to separate bassenger minne.
Det er en felles pool av minne hvor du starter, i denne visuelle
du starter på bunnen og begynne å fylle opp
fra bunnen sammen med stabelen, og du start øverst og begynner å fylle seg
ovenfra og ned med haugen.
Men det virkelig er samme basseng, det er bare
forskjellige steder, forskjellige steder i minnet som blir tildelt.
Og du kan kjøre ut av minne ved å enten ha
haugen gå hele veien til bunnen, eller ha
stabelen gå hele veien til toppen, eller å ha haugen og stakken
møte opp mot hverandre.
Alle disse kan være forhold som forårsaker programmet
å kjøre ut av minnet.
Så hold det i tankene.
Når vi snakker om haugen og stakken
vi egentlig snakker om samme generelle del av minnet, bare
ulike deler av at minnet.
>> Så hvordan får vi dynamisk allokert minne i første omgang?
Hvordan få vårt program minne som det kjører?
Vel C gir en funksjon som heter malloc, minne tildeler, som
du ringer til, og du passerer i hvor mange byte minne som du ønsker.
Så hvis programmet kjører og du vil ha et heltall runtime,
du kan Mallock fire byte minne, parenteser malloc fire.
>> Mallock vil gå gjennom ser gjennom haugen,
fordi vi er dynamisk tildele minne,
og det vil komme tilbake til deg en peker til at minnet.
Det gir deg ikke at memory-- det gir ikke det et navn,
det gir deg en peker til det.
Og så det er derfor igjen sa jeg at det er viktig å kanskje
har sett pekere video før vi kommer for langt inn i dette.
Så malloc kommer til å gi deg tilbake en peker.
>> Hvis Mallock ikke kan gi deg noe minne fordi du har kjørt ut,
det vil gi deg tilbake en nullpeker.
Husker du hva som skjer hvis vi prøve og dereference en nullpeker?
Vi lider en SEG feil, ikke sant?
Det er nok ikke bra.
>> Så hver gang du ringer til malloc du alltid, alltid
trenger å sjekke hvorvidt pekeren det ga deg tilbake er null.
Hvis det er, må du avslutte programmet fordi hvis du prøver og dereference
nullpeker du kommer å lide en segmentering feil
og programmet er kommer til å krasje uansett.
Så hvordan gjør vi statisk få et heltall?
>> int x.
Vi har sikkert gjort det en haug med ganger, ikke sant?
Dette skaper en variabel kalt x som lever på stakken.
Hvordan kan vi dynamisk å bli tildelt et heltall?
Int stjerners px tilsvarer malloc fire.
>> Eller mer hensiktsmessig vi vil si int stjerners px
tilsvarer malloc størrelsen på int, bare for å kaste litt færre
magiske tall rundt vårt program.
Dette kommer til å få for oss fire byte minne fra haugen,
og pekeren vi får tilbake til det kalles px.
Og så akkurat som vi har gjort tidligere vi
kan dereference px til tilgang til dette minnet.
Hvordan får vi et tall fra brukeren?
Vi kan si int x lik få int.
Det er ganske grei.
Hva om vi ønsker å skape en matrise av x flyter som lever på stakken?
flyte stack_array-- det er navnet av våre array-- hakeparenteser x.
Som vil skape for oss en matrise av x flyter som lever på stakken.
Vi kan lage en rekke flyter som lever på haugen, også.
Syntaksen kan se en litt mer tungvint,
men vi kan si float stjerners heap_array lik
malloc x ganger størrelsen av flottøren.
Jeg trenger nok plass til å holde x flyt verdier.
Så sier jeg trenger 100 flyter, eller 1.000 flyter.
Så i så fall ville det være 400 byte for 100 flyter,
eller 4000 byte for 1000 flyter, fordi hver flottør tar opp
fire byte av plass.
>> Når du har gjort dette kan jeg bruke hakeparentes syntaks på heap_array.
Akkurat som jeg ville gjort på stack_array, jeg kan få tilgang til sine elementer enkeltvis
bruker heap_array null, heap_array en.
Men husker grunnen til at vi kan gjøre det er fordi navnet på en matrise i C
er egentlig en peker til denne matrisen første element.
Så det faktum at vi erklære en rekke flyter på stakken her
er faktisk litt misvisende.
Vi er i andre kodelinje der
også lage en peker til en del av minne om at vi da gjøre noe arbeid med.
>> Her er det store problemet med dynamisk allokert minne om,
og dette er grunnen til at det er virkelig viktig å utvikle noen gode vaner
når du jobber med det.
I motsetning til statisk erklært minne, minne
ikke automatisk tilbake til systemet når funksjonen er ferdig.
Så hvis vi har hoved, og Hoved kaller en funksjon
f, når f ferdig hva det gjør og returnerer kontroll av programmet
tilbake til hovedsiden, hele minnet som f brukes er gitt tilbake.
Den kan brukes igjen av et annet program,
eller en annen funksjon som blir kalt senere i main.
Det kan bruke den samme minne om igjen.
>> Hvis du dynamisk allokere minne om
Du må uttrykkelig fortelle system som du er ferdig med det.
Det vil holde på det for deg, som kunne føre til et problem med å gå tom dere
minne.
Og faktisk vi noen ganger refererer til dette som en minnelekkasje.
Og noen ganger disse minnelekkasjer faktisk kan være veldig ødeleggende
for systemytelse.
>> Hvis du er en hyppig Internett-bruker du kan bruke enkelte nettlesere,
og jeg vil ikke nevne navn her, men er det noen nettlesere der ute
som er beryktet for faktisk å ha minnelekkasjer som ikke får løst.
Og hvis du lar din nettleser åpen for en svært lang tid, dager
og dager, eller uker, du noen ganger kanskje merke at systemet
er å kjøre veldig, veldig sakte.
Og grunnen til det er at leseren har bevilget minne,
men da ikke fortalt systemet at det er gjort med det.
Og så blir det mindre minne tilgjengelig for alle dine andre programmer
til å dele, fordi du er leaking-- som nettleser
Programmet er lekker minne.
Hvordan gir vi minne tilbake når vi er ferdig med det?
Vel heldigvis er det en veldig enkel måte å gjøre det.
Vi bare frigjøre den.
Det er en funksjon som heter gratis, den godtar en peker til minnet,
og vi er godt å gå.
>> Så la oss si at vi er i midt i vårt program,
vi ønsker å malloc 50 tegn.
Vi ønsker å malloc en matrise som kan stand til å holde 50 tegn.
Og når vi får en peker tilbake til det, at pekeren navn er ordet.
Vi gjør hva vi er kommer til å gjøre med ord,
og når vi er gjort vi bare frigjøre den.
Og nå har vi kommet tilbake de 50 bytes minne tilbake til systemet.
Noen andre funksjoner kan bruke dem.
Vi trenger ikke å bekymre deg for å ha fått en minnelekkasje fordi vi har frigjort ord.
Vi har gitt minnet tilbake, så vi er ferdig med å jobbe med det.
Så det er tre gylne regler som bør
holdes i bakhodet når du er dynamisk tildele minne
med malloc.
Hver blokk med minne som du malloc må frigjøres
før programmet er ferdig utført.
Nå igjen, i apparatet eller i IDE denne typen skjer for deg uansett
når you-- dette vil skje uansett når programmet er avsluttet,
alt minnet vil bli utgitt.
Men det er generelt god koding praksis å alltid, når du er ferdig,
frigjøre hva du har mallocd.
>> Når det er sagt, eneste som du har mallocd bør bli frigjort.
Hvis du statisk erklære en heltall, int x semikolon,
som lever på stakken, du ikke så lurt å frigjøre x.
Så bare ting som du har mallocd bør bli frigjort.
>> Og til slutt, ikke gratis noe to ganger.
Som kan føre til annen merkelig situasjon.
Så alt du har mallocd må bli frigjort.
Bare ting som du har malloc bør bli frigjort.
Og ikke gratis noe to ganger.
>> Så la oss gå gjennom et eksempel her av hva noen dynamisk allokert
minne kan se ut som blandet på med litt statisk minne.
Hva kan skje her?
Se om du kan følge sammen og gjett hva som er
kommer til å skje når vi går gjennom alle disse linjer med kode.
>> Så vi sier int m.
Hva skjer her?
Vel, dette er ganske grei.
Jeg oppretter et heltall variabel kalt m.
Jeg farge det grønt, fordi det er den fargen
som jeg bruker når jeg snakker ca heltallsvariabler.
Det er en boks.
Det kalles m, og du kan lagre heltall innsiden av det.
>> Hva om jeg da si int stjerne en?
Vel det er ganske lik.
Jeg oppretter en boks kalt en.
Det er stand til å holde int stjerner, pekere til heltall.
Så jeg fargelagt det grønn-ish også.
>> Jeg vet det har noe å gjøre med et heltall,
men det er ikke i seg selv et heltall.
Men det er ganske mye den samme ideen.
Jeg har laget en boks.
Begge disse rett nå bor på stakken.
Jeg har gitt dem begge navnene.
>> int stjerners b tilsvarer malloc størrelsen på int.
Dette kan være litt vanskelig.
Ta et øyeblikk og tenke over hva du forventer å skje på dette diagrammet.
int stjerners b tilsvarer malloc størrelsen på int.
>> Vel, dette betyr ikke bare lage en boks.
Dette skaper faktisk to bokser.
Og det bånd, det også etablerer et punkt i et forhold.
Vi har tildelt en blokk minne på haugen.
Legg merke til at den øverste høyre boksen det har ikke et navn.
>> Vi mallocd det.
Den eksisterer på haugen.
Men b har et navn.
Det er en peker variabel kalt b.
Som lever på stakken.
>> Så det er et stykke minne som peker til en annen.
b inneholder adressen av den minneblokk.
Det har ikke et navn på annen måte.
Men det peker på stedet.
Så når vi sier int stjerners b lik malloc størrelsen på int, at akkurat der,
at pilen som dukket opp på høyre side er det, at hele greia,
Jeg vil ha det vises igjen, er hva som skjer.
Alt dette skjer i som eneste linje med kode.
Nå får vi litt mer grei igjen.
en lik tegnet m.
Husker du hva en lik tegnet m er?
Vel det er en får m adresse.
Eller sagt mer skjematisk en peker til m.
>> a er lik b.
OK så her er en annen.
A er lik b.
Hva kommer til å skje til diagrammet denne gangen?
>> Vel husker at Oppdraget operatør verk
ved å tildele verdien på rett til verdien på venstre side.
Så i stedet for en peker til m, en nå peker til samme sted som b poeng.
en peker ikke til b, en påpeker hvor b poeng.
>> Hvis en spiss til B som ville har vært en lik-tegnet b.
Men i stedet en lik b bare betyr at og b er nå
peker til samme adresse, fordi Innsiden av b er bare en adresse.
Og nå inne i en er den samme adressen.
m er lik 10, sannsynligvis den enkleste ting
vi har gjort i en liten bit.
Sett 10 i boksen.
Stjerne b er lik m pluss to, husker fra vår pekere video hva star b betyr.
Vi kommer til å deferanseoperasjon b og put viss verdi i den minnelokasjon.
I dette tilfelle 12.
>> Så når vi deferanseoperasjon et poeng av husker vi bare reise ned pilen.
Eller sagt på en annen måte, vi gå til at minneadresse
og vi manipulere det på noen måte.
Vi satt noen verdi i det.
I dette tilfellet stjerners b lik m pluss to er bare
gå til variabelen peker til b, gå til minne peker til b,
og sette m pluss to der inne, 12.
>> Nå har jeg fri b.
Hva skjer når jeg fri b?
Husk hva jeg sa frie midler.
Hva er det jeg sier når jeg fri b?
>> Jeg er ferdig med å jobbe med det, ikke sant?
Jeg egentlig gi opp minnet.
Jeg gir den tilbake til systemet.
Jeg trenger ikke dette lenger er hva jeg forteller dem, OK?
>> Nå hvis jeg sier stjerne en tilsvarer 11 kan du sannsynligvis
allerede si at noe dårlig kommer til å skje her, ikke sant?
Og ja hvis jeg prøvde at jeg sannsynligvis ville lide en segmentering feil.
Fordi nå, selv om tidligere at mengde minne
var noe som jeg hadde adgang til, på dette punktet
nå er jeg tilgang til minne som er ikke lovlig for meg å få tilgang.
>> Og som vi vil sannsynligvis husker, når vi tilgang til minnet
at vi ikke er ment å berøre, det er den vanligste årsaken
av en segmentering utsette. Og så mitt program
ville krasje hvis jeg prøvde å gjøre dette.
Så igjen er det en god idé å få god praksis og gode vaner inngrodd
når du arbeider med malloc og gratis, slik at du ikke lider segmentering
feil, og at du bruker din dynamisk allokert
minne ansvarlig.
>> Jeg er Doug Lloyd dette er CS50.