[Přehrávání hudby]
>> DOUG LLOYD: OK, takže návrh, Před spuštěním zde.
Pokud jste sledovali video na na ukazatele budete chtít dělat tak jako první.
Vzhledem k tomu, toto video je další způsob práce s ukazateli.
>> Takže to bude mluvit o některých pojmů
že budeme povídat v na ukazatele videa, a my jsme
bude lesk nad nimi teď, za předpokladu, že jsou již
tak nějak pochopil.
Tak to je jen váš fér varování že pokud jste viděl toto video
a vy jste neviděli ukazatele video, by to mohlo nějak
létat nad hlavou, trochu.
A tak by to mohlo být lepší se dívat na to v tomto pořadí.
>> Takže jsme již viděli jeden způsob práce s ukazateli,
což je deklarujeme variabilní, a pak jsme
deklarovat další proměnnou, ukazatel proměnná, která ukazuje na to.
Proto jsme vytvořili proměnná s názvem, máme
vytvořil druhou proměnnou s názvem, a upozorňujeme, že Druhá proměnná
na to jako první.
Tento druh má Problémem však, protože to
vyžaduje, abychom přesně věděli, kolik paměti, že jsme
bude potřebovat ve chvíli, Náš program je sestaven.
>> Proč tomu tak je?
Vzhledem k tomu, musíme být schopni pojmenovat nebo identifikovat všechny možné proměnných
můžeme setkat.
Mohli bychom mít pole, které by mohlo být schopný pojmout velké množství informací,
ale je to stále není přesně dostatečně přesná.
Co když nevíme, co když budeme mít tušení
kolik budeme potřebovat v době kompilace?
Nebo co když náš program bude běžet opravdu dlouhou dobu,
přijímat různé uživatele dat, a můžeme opravdu
odhadnout, zda jsme bude potřebovat 1000 kusů?
>> Není to tak, můžeme říkají, na příkazovém řádku
Zadejte, kolik položek si myslíte, že budete potřebovat.
No co když odhad je špatně?
Dynamické přidělování paměti druh umožňuje nám cestu
obejít tento konkrétní problém.
A to, jak to dělá je pomocí ukazatelů.
>> Můžeme použít odkazy na získat přístup k dynamicky
přidělené paměti, paměti, která je přidělen jako váš program běží.
Není to přiděleny v době kompilace.
Když dynamicky přidělovat Paměť pochází z bazénu
paměti známý jako haldy.
Dříve je celá paměť máme pracuje se v průběhu
byl pocházející z bazénu paměti známý jako zásobníku.
Dobrým způsobem, jak všeobecně mějte na mind-- a tomto pravidle
nemusí vždy platit, ale do značné míry téměř
vždy myslí true-- je, že každý čas si dát název proměnné it
pravděpodobně žije na zásobníku.
A pokaždé, když ne vykazovat proměnlivou jméno,
které můžete dělat s dynamické paměti alokace, žije na haldě.
>> Teď jsem trochu prezentovat to jako v případě, že je tyto dva bazény paměti.
Ale možná viděli toto diagram, který je obecně
znázornění Jaké paměťové vypadá,
a nebudeme se starat o všem Hmota v horní a dolní části.
To, co zajímá je tato část v prostřední tady, haldy a zásobník.
Jak můžete vidět při pohledu na tomto diagramu,
Tyto skutečnosti nejsou dvou oddělené bazény paměti.
Je to jedna společná pool paměti kde začít, v tomto vizuální
začnete v dolní části a začít vyplnění
ode dna s zásobníku, a vy začínají na horní a zahájení doplňování
shora dolů s haldy.
Ale je to opravdu je Stejný bazén, je to jen
různých místech, různá umístění v paměti, které jsou přiděleny.
A můžete dojdou paměť buď s
halda jet celou cestu ke dnu, nebo se
zásobníku jet celou cestu na vrchol, nebo má haldy a zásobníku
setkat se proti sobě.
Všechny z nich mohou být podmínky které způsobují program
spustit nedostatek paměti.
Takže mějte na paměti, že.
Když mluvíme o halda a zásobník
jsme opravdu mluvíme o stejné obecné kus paměti, jen
různé části této paměti.
>> Tak jak se dostaneme dynamicky přidělené paměti v první řadě?
Jak se dostat náš program paměť, jak to běží?
No C poskytuje funkci nazvanou malloc, paměť alokátor, který
voláte na, a ty předat kolik bajtů paměti, které chcete.
Takže pokud váš program běží a chcete integer runtime,
můžete Mallocka čtyři byty paměť, malloc závorky čtyři.
>> Mallock projde hledá přes haldy,
protože jsme dynamicky přidělování paměti,
a navrátím se k vám ukazatel na této paměti.
To nedává vám, že memory-- nedává to jméno,
to vám dává ukazatel na něj.
A tak to je důvod, proč jsem zase řekl, že je důležité možná
Sledoval ukazatele videa než se dostaneme příliš daleko do toho.
Tak malloc to bude vám zpět ukazatel.
>> Pokud Mallock nemůže dát vám některý paměť, protože jste dojdou,
to bude vám zpět ukazatele null.
Pamatuješ si, co se stane, když vyzkoušet a dereference null ukazatel?
Trpíme poruchu seg, že jo?
To je asi není dobré.
>> Takže pokaždé, když voláte vás malloc vždycky, vždycky
je třeba ověřit, zda je nebo není ukazatel, že vám dal zpátky, je null.
Pokud ano, budete muset ukončit svůj program protože pokud se pokusíte a dereference
ukazatele null budete trpět poruchy segmentace
a váš program je spadne tak jako tak.
Tak jak jsme staticky získat celé číslo?
>> int x.
Jsme pravděpodobně udělal banda z časů, je to tak?
To vytváří proměnnou s názvem x, která žije v zásobníku.
Jak můžeme dynamicky získat číslo?
Int hvězda px rovná malloc 4.
>> Nebo více vhodně bychom říci, int hvězda px
rovná malloc velikost int, jen hodit některé méně
Magická čísla kolem našeho programu.
To se chystá získat pro nás Čtyři bajtů paměti z haldy,
a ukazatel dostaneme zpět k ní, se nazývá px.
A pak už jen jako my máme provedeno již dříve jsme
může dereference PX přístup k této paměti.
Jak můžeme získat celé číslo od uživatele?
Dá se říci, int x rovná se dostat int.
To je docela jednoduché.
Co když chceme vytvořit pole z x plováky, které žijí ve frontě?
float stack_array--, že se jmenuje z našich array-- hranatých závorek x.
To bude vytvářet pro nás pole z x plováky, které žijí v zásobníku.
Můžeme vytvořit celou řadu plováků která žije na haldě, taky.
Syntaxe může vypadat trochu těžkopádné,
ale můžeme říci, float hvězda heap_array rovná
malloc x měří velikost plováku.
Potřebuji dostatek prostoru držet x s plovoucí desetinnou čárkou hodnoty.
Takže říct, že jsem potřebovat 100 plováky, nebo plováky 1000.
Takže v tomto případě by bylo 400 bytů pro 100 plováky,
nebo 4000 bajtů na 1000 plováky, protože každý float zabírá
čtyři byty prostoru.
>> Poté, co to mohu použít hranatou závorku syntax na heap_array.
Stejně jako bych na stack_array, já mohou individuálně přistupovat k její prvky
pomocí heap_array nula, heap_array jednu.
Ale vzpomínám, proč to můžeme udělat Je tomu tak proto název pole v C
je opravdu ukazatel na První prvek této matice je.
Takže k tomu, že jsme deklarování řada plováků na zásobníku zde
je vlastně trochu zavádějící.
Jsme opravdu v Druhý řádek kódu tam
také vytváří ukazatel na kus paměti, že jsme pak udělat nějakou práci s.
>> Zde je velký problém s dynamicky přidělené paměti však,
a to je důvod, proč je to opravdu důležité vytvořit nějaké dobré návyky
při práci s ním.
Na rozdíl od staticky deklaroval paměť, paměť
není automaticky vrácena do Systém, kdy je vaše funkce provádí.
Takže pokud máme hlavní, a Hlavní volá funkci
f, když f povrchové úpravy jak se to dělá a vrátí řízení programu
zpět na hlavní, všechny paměti že f použít, je vrácena zpět.
To může být znovu použit nějakým jiným programem,
nebo nějaké jiné funkce, která se zavolá později v main.
Je možné používat stejně paměť opět nad.
>> Pokud vás dynamicky alokovat paměť ačkoli
budete muset říct, systém, který jste s ním udělal.
Bude to držet to pro vás, které by mohly vedou k problému z vás běží
paměti.
A ve skutečnosti jsme někdy se odkazují na toto jako nevracení paměti.
A někdy tyto nevracení paměti může být ve skutečnosti opravdu zničující
na výkon systému.
>> Pokud jste častým uživatel internetu můžete použít některé webové prohlížeče,
a nebudu zde jmenovat jména, ale tam jsou některé webové prohlížeče venku
které jsou notoricky známé pro skutečně mají úniky paměti, které nejsou opraveny.
A pokud necháte Váš prohlížeč otevřené Po velmi dlouhou dobu, dny
a dny, nebo týdny, někdy všimnout, že ve vašem systému
běží opravdu, ale opravdu pomalu.
A důvod pro to je skutečnost, že prohlížeč má přidělené paměti,
ale pak neřekl systém že se to dělá s ním.
A tak, že opustí méně paměti k dispozici pro všechny vaše jiných programů
muset podělit, protože jsi leaking--, že webový prohlížeč
Program je netěsní paměti.
Jak můžeme dát paměť zpět když jsme s ním udělal?
No naštěstí je to velmi snadný způsob, jak to udělat.
Právě jsme ho uvolnit.
K dispozici je funkce nazvaná zdarma, přijímá ukazatel na paměti,
a my jsme dobré jít.
>> Takže řekněme, že jsme v Uprostřed našeho programu,
Chceme malloc 50 znaků.
Chceme malloc pole, které může schopné pojmout 50 znaků.
A když se dostaneme ukazatel zpět že název přes tento ukazatel je slovo.
Děláme, co máme dělat s slovu,
a pak, když jsme udělali jsme prostě ho uvolnit.
A teď jsme se vrátili ty 50 bajtů paměti zpět do systému.
Některé další funkce mohou používat.
Nemusíme se starat o utrpení nevracení paměti, protože jsme osvobozeni slovo.
Dali jsme paměť zpět, takže jsme skončili práci s ním.
Takže tam jsou tři zlatých pravidel, která by měla
třeba mít na paměti vždy, když budete dynamicky přidělování paměti
s malloc.
Každý blok paměti, která vy malloc musí být uvolněn
Před programu dokončení spuštění.
Nyní opět do spotřebiče nebo v IDE tento druh stane pro vás tak jako tak
kdy vás-- se to stane tak jako tak je-li váš program ukončen,
celá paměť se uvolní.
Ale je to obecně dobrá kódování praxe vždy, když budete hotovi,
osvobodit, co jste mallocd.
>> To znamená, že pouze věci, které nemáš mallocd by měl být osvobozen.
Pokud staticky deklarovat integer, int x středník,
která žije na zásobníku, budete nemají pak chtít osvobodit x.
Takže jen věci, které jste mallocd by měl být osvobozen.
>> A konečně, ne volné něco dvakrát.
To může vést k další divná situace.
Takže vše, co jsem mallocd musí být osvobozen.
Pouze věci, které jste si malloc by mělo být uvolněno.
A ne bez něco dvakrát.
>> Takže pojďme projít příklad zde z toho, co někteří dynamicky přidělené
Paměť může vypadat jako smíšené v s nějakým statické paměti.
Co by se mohlo stát tady?
Uvidíme, jestli můžete sledovat spolu, a hádejte, co je
se stane, jak jsme jít přes všechny tyto řádky kódu.
>> Takže říkáme int m.
Co se tady děje?
No to je docela jednoduché.
I vytvořit celočíselnou proměnnou s názvem m.
I barva je zelená, protože to je barva
který používám, když mluvím o celočíselné proměnné.
Je to krabice.
Říká se tomu m, a můžete ukládat celá čísla uvnitř něj.
>> Co když jsem pak řekl int hvězdičkou?
No to je dost podobné.
Jsem vytvořit krabice volal.
Je schopna pojmout int hvězdy, ukazatele na celá čísla.
Takže jsem to barvení Green-ish stejně.
>> Vím, že to má něco co do činění s celým číslem,
ale to není samo o sobě celé číslo.
Ale je to skoro stejné nápad.
Vytvořil jsem krabici.
Obě tyto práva nyní žijí na zásobníku.
Já jsem jim dal obě jména.
>> int hvězda b rovná malloc velikost int.
Tohle by mohlo být trochu složitější.
Vezměte druhý a přemýšlet o tom, co by se očekávat, že se stane v tomto schématu.
int hvězda b rovná malloc velikost int.
>> No to není jen vytvořit jednu kolonku.
Toto vlastně vytváří dvě krabice.
A to vazby, ale také stanovuje bod ve vztahu.
Máme přiděleno jeden blok paměti na haldě.
Všimněte si, že v pravém horním rohu box tam nemá jméno.
>> Mallocd jsme to.
To existuje na haldě.
Ale b má jméno.
Je to ukazatel proměnnou s názvem b.
Která žije na zásobníku.
>> Takže je to kus paměti , který odkazuje na jiný.
b obsahuje adresu z tohoto bloku paměti.
Nemá jméno jinak.
Ale to poukazuje na to.
Takže když řekneme int star b se rovná Velikost malloc int, že právě tam,
že šipka, která vyskočila na pravá strana tam, že celá ta věc,
Budu mít to vypadat Znovu, je to, co se stane.
To vše se děje v že jediný řádek kódu.
Teď budeme mít trochu víc přímočaré znovu.
A je rovna ampersand m.
Vzpomínáte si, co si rovná ampersand m je?
No to je dostane adresu M.
Nebo dát více schematicky, A ukazuje na m.
>> A je rovna b.
OK, takže tady je další.
A je rovna b.
Co se bude dít diagramu tentokrát?
>> No připomenout, že Operátor přiřazení práce
přiřazením hodnoty na straně právo na hodnotu vlevo.
Takže místo toho, ukazovací do m, je nyní poukazuje na stejném místě, které b bodů.
neukazuje na B, A místa, kde se b bodů.
>> Pokud se ukázal na B, která by byli se rovná ampersand b.
Ale místo toho se rovná b jen Znamená to, že a a b jsou nyní
směřující na stejnou adresu, protože uvnitř b je jen adresa.
A teď uvnitř a je stejná adresa.
m se rovná 10, pravděpodobně Nejjednodušší věc
udělali jsme v trochu.
Dejte 10 v krabici.
Hvězda b se rovná m plus 2, převezme zpět od náš ukazatele video Co hvězda b znamená.
Budeme dereference b a put nějakou hodnotu v tomto paměťovém místě.
V tomto případě 12.
>> Takže když jsme se dereference bodu vzpomínám jen jsme cestovat dolů na šipku.
Jinak řečeno, my jděte na tuto adresu paměti
a my jsme s ním manipulovat nějakým způsobem.
Dali jsme nějakou hodnotu tam.
V tomto případě hvězdičkový B rovná se M plus 2 je prostě
jít do proměnné ukázal na B, přejít do paměti ukázal na B,
a dal m plus 2 tam, 12.
>> Teď jsem osvobodit b.
Co se stane, když jsem se osvobodit b?
Vzpomeňte si, co jsem řekl, volné prostředky.
Co jsem řekl, když jsem se osvobodit b?
>> Skončil jsem s ní pracovat, ne?
Já v podstatě vzdát paměti.
Dávám ji zpět do systému.
Nepotřebuju to už je to, co jsem jim řekl, OK?
>> Teď, když řeknu hvězdičkou se rovná 11 můžete pravděpodobně
Již, že něco špatného říct, se stane, že?
A skutečně, když jsem se snažil, že bych asi by utrpěla chybu segmentace.
Vzhledem k tomu, nyní, i když předtím, že kus paměti
bylo něco, co jsem měl přístupu k nim v tomto bodě
teď jsem přístup k paměti, že není legální pro mě přístup.
>> A jak budeme pravděpodobně vzpomínáte, když jsme se přístup k paměti
že jsme neměli na dotek, to je nejčastější příčinou
z segmentace porucha. A tak se můj program
zřítí, když jsem se snažil to udělat.
Takže opět je to dobrý nápad, aby si dobře praxe a dobré návyky hluboce zakořeněné
Při práci s malloc a zdarma, takže nemusíte trpět segmentaci
chyby, a že používáte vaše dynamicky přidělené
paměť zodpovědně.
>> Jsem Doug Lloyd je to CS50.