[MUSIK SPELA] DOUG LLOYD: OK så ett förslag innan här. Om du inte har sett videon på pekare som du kanske vill göra det först. Eftersom den här videon är en annan sätt att arbeta med pekare. Så det kommer att prata om vissa begrepp som vi täcker i pekare video, och vi är kommer att släta över dem nu, förutsatt att de är redan sorts förstådd. Så det är bara din skälig varning att om du ser den här videon och du har inte sett pekare video, kanske det slags flyga över huvudet lite. Och så det kan vara bättre att titta på det i den ordningen. Så vi har redan sett en sätt att arbeta med pekare, som är deklarerar vi en variabel och sedan vi förklara en annan variabel, en pekare variabel, pekar det till den. Så vi har skapat en variabel med ett namn, vi har skapade en andra variabel med ett namn, och vi peka att andra variabel vid den första. Denna typ av har en problem men eftersom det kräver att vi vet exakt hur mycket minne som vi är kommer att behöva för tillfället vårt program kompileras. Varför? Eftersom vi måste kunna namnge eller identifiera alla möjliga variabler vi kan stöta på. Vi kanske har en matris som kan vara kunna hålla en hel del information, men det är fortfarande inte precis tillräckligt exakt. Vad händer om vi inte vet, tänk om vi har ingen aning hur mycket vi behöver vid kompileringen? Eller vad händer om vårt program kommer pågå under en väldigt lång tid, acceptera olika användare data och vi kan inte riktigt bedöma om vi är kommer att behöva 1.000 enheter? Det är inte som vi kan säger på kommandoraden ange hur många objekt du tror att du behöver. Och vad om det gissning är fel? Dynamisk minnesallokering sorts tillåter oss vägen att komma runt detta problem. Och den gör det är att använda pekare. Vi kan använda pekare till få tillgång till dynamiskt allokerat minne, minne som är fördelas enligt programmet körs. Det är inte tilldelas vid kompileringen. När du dynamiskt fördela minne det kommer från en pool minne kallas högen. Tidigare hela minnet vi har arbetat med under loppet har kommit från en pool minne som kallas stapeln. Ett bra sätt att allmänt hålla mind-- och denna regel inte alltid hålla sant, men ganska mycket nästan alltid håller true-- är att varje gång du ger ett variabelnamn det förmodligen bor på stacken. Och varje gång du gör inte ge en variabel ett namn, som du kan göra med dynamiskt minne tilldelning, lever den på högen. Nu är jag typ att presentera detta som om det finns dessa två pooler av minne. Men du kanske har sett denna schema, som i allmänhet är en representation av hur minne ser ut, och vi kommer inte att bry sig om alla grejer på toppen och botten. Vad vi bryr oss om är denna del i mitten här, hög och stack. Som ni kan se av titta på detta diagram, dessa faktiskt inte två separata pooler minne. Det är en delad pool av minne där du börjar i denna visuella du börjar längst ner och börja fylla upp från botten med bunten, och ni börja i toppen och börja fylla upp uppifrån och ner med högen. Men det är verkligen samma pool, det är bara olika platser, olika platser i minnet som fördelas. Och du kan få slut på minne genom att antingen ha högen gå hela vägen till botten, eller har stacken gå hela vägen till toppen, eller som har högen och stapeln möta upp mot varandra. Alla dessa kan vara villkor som orsakar ditt program att få slut på minne. Så ha det i åtanke. När vi talar om högen och stack vi egentligen talar om samma allmänna bit av minne, olika delar av detta minne. Så hur får vi dynamiskt allokerat minne i första hand? Hur vårt program får minne som det körs? Väl C ger en funktion som kallas malloc, minnesallokering, som du ringer ett samtal till och du passerar in hur många byte minne som du vill. Så om ditt program körs och du vill ha en heltal runtime, du kanske Mallock fyra byte minne, parenteser malloc fyra. Mallock kommer att gå igenom tittar genom högen, eftersom vi är dynamiskt allokering av minne, och det kommer tillbaka till dig en pekare till detta minne. Det är inte ge dig den memory-- den inte ge den ett namn, det ger dig en pekare till det. Och så det är därför återigen sa jag att det är viktigt att kanske har sett pekare video innan vi kommer för långt in i detta. Så malloc kommer att ge dig tillbaka en pekare. Om Mallock inte kan ge dig något minnet eftersom du har slut, det ska ge dig tillbaka en nollpekare. Kommer du ihåg vad som händer om vi försöka dereference en nollpekare? Vi lider en seg fel, eller hur? Det är förmodligen inte bra. Så varje gång du ringer ett samtal att malloc dig alltid, alltid måste kontrollera om inte pekaren det gav dig tillbaka är noll. Om det är, måste du avsluta ditt program eftersom om du försöker och dereference noll pekaren du ska att drabbas av en segmentering fel och ditt program är kommer att krascha ändå. Så hur gör vi statiskt erhålla ett heltal? int x. Vi har antagligen gjort det ett gäng gånger, eller hur? Detta skapar en variabel som heter x som lever på stacken. Hur kan vi dynamiskt få ett heltal? Int stjärna px lika malloc 4. Eller mer korrekt vi skulle säga int stjärna px lika malloc storlek int, bara för att kasta lite färre Magic Numbers runt vårt program. Detta kommer att få för oss fyra byte minne från högen, och pekaren vi får tillbaka till det kallas px. Och sedan bara som vi har gjort tidigare vi kan dereference px till sjunga detta minne. Hur får vi ett heltal från användaren? Vi kan säga int x lika få int. Det är ganska enkelt. Vad händer om vi vill skapa en array av x flottar som lever på stacken? flyta stack_array-- det är namnet av våra array-- hakparentes x. Det kommer att skapa för oss en array av x flottörer som lever på stacken. Vi kan skapa en matris med flottörer som lever på högen, alltför. Syntaxen kan se en lite mer besvärligt, men vi kan säga float stjärn heap_array lika malloc x gånger större än flottörens. Jag behöver tillräckligt med utrymme för att hålla x flyttalsvärden. Så säger jag behöver 100 flottar, eller 1000 flyter. Så i så fall skulle det vara 400 byte för 100 flottar, eller 4000 byte för 1000 flottar, eftersom varje flottör tar upp fyra byte av utrymme. Efter detta kan jag använda klammer syntaxen på heap_array. Precis som jag gör på stack_array jag kan få tillgång till sina element individuellt användning heap_array noll, heap_array en. Men minns anledningen till att vi kan göra det beror på att namnet på en matris i C är verkligen en pekare till att array första elementet. Så det faktum att vi förklara en samling av flöten på stacken här är faktiskt lite missvisande. Vi är verkligen i andra kodrad där också skapa en pekare till en del av minne som vi sedan göra en del arbete med. Här är det stora problemet med allokeras dynamiskt minne men, och det är därför det är verkligen viktigt att utveckla några goda vanor när du arbetar med det. Till skillnad från statiskt deklarerade minne, ditt minne inte automatiskt tillbaka till systemet när din funktion är klar. Så om vi har huvud, och Huvud anropar en funktion f, när f finish vad det gör och returnerar styrning av programmet tillbaka till huvud, allt minne att f används ges tillbaka. Den kan användas på nytt av något annat program, eller någon annan funktion som anropas senare i main. Det kan använda samma minne igen. Om du dynamiskt allokera minne om du måste specifikt tala om system som du är klar med det. Det kommer att hålla fast vid det för dig, som skulle kunna leda till ett problem av er att ta slut minne. Och faktum är att vi ibland hänvisar till detta som en minnesläcka. Och ibland dessa minnesläckor kan faktiskt vara riktigt förödande för systemets prestanda. Om du är en flitig Internetanvändare du kan använda vissa webbläsare, och jag kommer inte att nämna namn här, men det finns vissa webbläsare ute som är ökända för att faktiskt ha minnesläckor som inte få fast. Och om du lämnar din webbläsare öppet för en mycket lång tidsperiod, dagar och dagar, eller veckor, du ibland kanske märker att ditt system körs riktigt, riktigt långsamt. Och anledningen till det är att webbläsaren har tilldelat minne, men sedan inte veta systemet att det görs med den. Och så som lämnar mindre minne tillgängliga för alla dina andra program att behöva dela, eftersom du är leaking-- att webbläsare Programmet läcker minne. Hur ger vi minnet tillbaka När vi är klara med det? Tja lyckligtvis är det en mycket enkelt sätt att göra det. Vi frigör det bara. Det finns en funktion som kallas fri, det accepterar en pekare till minne, och vi är bra att gå. Så låt oss säga att vi är på mitten av vårt program, Vi vill malloc 50 tecken. Vi vill malloc en array som kan kan hålla 50 tecken. Och när vi får en pekare till att att pekaren heter ord. Vi gör vad vi är ska göra med ord, och sedan när vi är gjort vi bara befria den. Och nu har vi återvänt dessa 50 byte minne tillbaka till systemet. Någon annan funktion kan använda dem. Vi behöver inte oroa dig för att lida en minnesläcka eftersom vi har befriat ord. Vi har gett minnet tillbaka, så vi är klar arbetar med det. Så det finns tre gyllene regler som bör hållas i åtanke när du är dynamiskt allokera minne med malloc. Varje block av minne som du malloc måste befrias innan ditt program slutar köra. Nu igen, i apparaten eller i IDE denna typ av händer för dig ändå när du-- detta kommer att ske i alla fall när programmet avslutas, allt minne kommer att släppas. Men det är i allmänhet bra kodning vana att alltid, när du är klar, befria vad du har mallocd. Som sagt, enda som du har mallocd ska friges. Om du statiskt deklarera en heltal, int x semikolon, som lever på stacken, du inte sedan vill frigöra x. Så bara saker som du har mallocd bör friges. Och slutligen, inte fri något två gånger. Det kan leda till annan konstig situation. Så allt som du har mallocd måste friges. Bara saker som du har malloc bör friges. Och gör inte fri något två gånger. Så låt oss gå igenom ett exempel här av vad vissa dynamiskt allokerad minne kan se ut blandad in med vissa statiskt minne. Vad kan hända här? Se om du kan följa tillsammans och gissa vad som är kommer att hända när vi går genom alla dessa rader kod. Så vi säger int m. Vad händer här? Ja detta är ganska enkelt. Jag skapar en heltalsvariabel kallad m. Jag färg det grönt, eftersom det är färgen som jag använder när jag talar om heltalsvariabler. Det är en låda. Det kallas m, och du kan lagra heltal inne i det. Vad händer om jag sedan säga int stjärna a? Jo det är ganska likartade. Jag skapar en ruta som kallas en. Det är kapabel innehav int stjärnor, pekare till heltal. Så jag färga det grönt-ish också. Jag vet att det har något att göra med ett heltal, men det är inte i sig ett heltal. Men det är ganska mycket samma idé. Jag har skapat en låda. Båda dessa rätt nu bor på stacken. Jag har gett dem båda namnen. int stjärna B lika malloc storlek int. Detta kan vara lite knepigt. Ta en sekund och fundera på vad du förväntar sig att hända på det här diagrammet. int stjärna B lika malloc storlek int. Ja detta inte bara skapa en ruta. Detta skapar faktiskt två lådor. Och det binder, det fastställs också en punkt i ett förhållande. Vi har tilldelats ett kvarter minne på högen. Lägg märke till att den övre högra rutan det inte har ett namn. Vi mallocd det. Det finns på högen. Men B har ett namn. Det är en pekare variabel som heter b. Som lever på stacken. Så det är en bit av minne som pekar på en annan en. b innehåller adressen av detta minnesblock. Det har inte ett namn annars. Men den pekar på det. Så när vi säger int stjärna B lika malloc storlek int, att just där, att pilen som dök upp på höger sida där det hela, I have det verkar igen, är vad som händer. Allt detta händer i som enda rad kod. Nu ska vi få lite mer okomplicerad igen. en lika -tecken m. Minns ni vad en lika-tecken m är? Jo det är en får m adress. Eller lägga mer schematiskt, en poäng till m. a är lika med b. OK så här är en annan. A är lika med f. Vad kommer att hända diagrammet här gången? Väl påminna om att tilldelningsoperator verk genom att tilldela värdet på rätt till värdet till vänster. Så i stället för en som pekar på m, en nu pekar på samma ställe som b punkter. en inte peka på b, en punkter där b poäng. Om ett spetsigt till b som skulle har varit en lika -tecken b. Utan i stället en lika b bara innebär att och b är nu pekar på samma adress, eftersom insidan av b är bara en adress. Och nu inne i en är samma adress. m är lika med 10, förmodligen enklaste sak vi har gjort i en liten bit. Placera 10 i rutan. Star B är lika med m plus 2, minns från våra pekare video vad stjärn b innebär. Vi kommer att dereference b och put ett värde i den minnesplatsen. I detta fall 12. Så när vi avreferera en punkt minns vi bara resa ner pilen. Eller annorlunda uttryckt, vi gå till den minnesadress och vi manipulerar det på något sätt. Vi sätter något värde i det. I detta fall stjärna B lika m plus 2 är bara gå till variabeln som utpekas av b, gå till minnet som utpekas av b, och sätta m plus 2 där, 12. Nu befria Ib. Vad händer när jag fri b? Kom ihåg vad jag sa fria medel. Vad säger jag när jag fri b? Jag är gjort arbetar med det, eller hur? Jag ger i huvudsak upp minnet. Jag ger det tillbaka till systemet. Jag behöver inte här längre är vad jag talar om för dem, OK? Nu om jag säger stjärn en lika 11 kan du förmodligen redan nu säga att något dåligt kommer att hända här, eller hur? Och faktiskt, om jag försökte att jag förmodligen skulle drabbas av en segmentering fel. För nu, även om tidigare att bit av minne var något som jag hade tillgång till, vid denna punkt nu är jag tillgång till minne som är inte lagligt för mig att få tillgång till. Och när vi kommer förmodligen minns när vi tillgång till minne att vi inte ska röra, det är den vanligaste orsaken av en segmente fel. Och så mitt program skulle krascha om jag försökte göra detta. Så återigen är det en bra idé att få bra praxis och goda vanor ingrodd när man arbetar med malloc och free, så att du inte lider segmente fel, och att du använder din dynamiskt allokerad minne ansvarsfullt. Jag är Doug Lloyd detta är CS50.