[MUZIKO Ludante]
>> DOUG LLOYD: OK do sugesto antaŭ komenci ĉi tie.
Se vi ne spektis la videon sur Montriloj vi volus fari tiel unue.
Ĉar tiu video estas alia labormetodo kun punteros.
>> Do ĝi estas tuj paroli pri iuj konceptoj
ke ni kovras en la Montriloj vídeo, kaj ni estas
tuj forgliti super ilin nun, supozante ke ili estas jam
ia komprenis.
Do tio estas nur via justa averto ke se vi vidas ĉi tiu vídeo
kaj vi ne vidis la punteros vídeo, ĝi eble ia
flugas super via kapo iomete.
Kaj tiel povus esti bona rigardi ĝin en tiu ordo.
>> Do ni jam vidis unu maniero labori kun punteros,
kio estas ni deklari variablo, kaj tiam ni
deklari alia variablo, montrilo variablo, kiu notas al tio.
Do ni kreis variablo kun nomo, ni havas
kreis duan variablo kun nomo, kaj ni atentigi ke dua variablo
en tiu unua.
Tian havas problemo kvankam, ĉar
postulas nin scias ĝuste kiom memoro ni estas
tuj bezonas la momento nia programo estas kompilita.
>> Kial estas tio?
Ĉar ni bezonas por povi citi aŭ identigi ĉiujn eblajn variablojn
Ni eble renkontos.
Ni povus havi tabelo ke povus esti povis teni multajn informojn,
sed ĝi estas ankoraŭ ne ĝuste preciza sufiĉa.
Kio se ni ne scias, kio se ni ne havas ideon
kiom ni bezonos dum la kompilado?
Aŭ kion se nia programo kuri por vere longa tempo,
akcepti diversajn uzanto datumoj, kaj ni ne povas vere
taksi ĉu ni estas tuj bezonas 1.000 ekzemplerojn?
>> Ne estas kiel ni povas diru ĉe la komandlinio
eniri kiomfoje Vi kredas ke vi bezonos.
Nu kion se tiu konjekto malĝustas?
Dinamika memoro atribuo ia permesas al ni la vojon
akiri ĉirkaŭ tiu aparta problemo.
Kaj la vojo ĝi faras estas uzante punteros.
>> Ni povas uzi punteros al ricevas aliron al dinamike
asignita memoro, memoro, kiu estas asignita kiel via programo kuras.
Ĝi ne estas asignitaj dum la kompilado.
Kiam vi dinamike asigni memoro ĝi venas de naĝejo
de memoro konata kiel la amaso.
Antaŭe tutan memoron ni havas estis laborante kun la paso
estis venanta de naĝejo de memoro nomata la pilo.
Bona maniero ĝenerale teni en mind-- kaj tiu regulo
ne ĉiam tenas vera, sed preskaux preskaŭ
ĉiam tenas true-- estas ke ajna tempo vi donas variablo nomo
probable vivas en la stako.
Kaj ajna tempo vi ne doni variablo nomo,
kiun vi povas fari kun dinamika memoro atribuo, vivas sur la monteto.
>> Nun mi specon de prezenti tion kiel se estas tiuj du naĝejoj de memoro.
Sed eble vi vidis tiun diagramo, kiu estas ĝenerale
reprezento de kion memoro similas,
kaj ni ne tuj zorgas pri ĉiuj la frandajxojn cxe la supro kaj la malsupro.
Kion ni zorgas pri estas tiu parto en la mezo tie, havaĵo kaj pilo.
Kiel vi povas vidi per rigardante tiun diagramon,
tiuj vere ne estas du apartaj naĝejoj de memoro.
Ĝi estas unu dividita naĝejo de memoro kie vi komencas, en ĉi vida
vi komenci ĉe la fundo kaj komenci rellenar
el la fundo kun la pilo, kaj vi komencu ĉe la supro kaj komenci rellenar
De la supro malsupren kun la havaĵo.
Sed vere estas la sama lageto, estas nur
malsamaj makuloj, malsamaj lokoj en memoro kiuj estas asignitaj.
Kaj vi povas kuri el memoro fare de aŭ havanta
la havaĵon iri la tutan vojon al la fundo, aŭ havas
la stako iri la tutan vojon al la supro, aŭ havantaj la havaĵon kaj la pilo
renkonti sin reciproke.
Ĉiuj el tiuj povas esti kondiĉoj kiuj kaŭzas vian programon
kuri el memoro.
Observu do, ke en menso.
Kiam ni parolas pri la havaĵon kaj la pilo
ni vere parolas pri la samaj ĝeneralaj eron de memoro, ĵus
malsamaj partoj de tiu memoro.
>> Do kiel ni preni dinamike asignita memoro en la unua loko?
Kiel nia programo akiras memoro kiel ĝi estas kurante?
Nu C provizas funkcio nomita malloc, memoro allocator, kiu
vi faras alvokon al, kaj pasas en kiom da bajtoj de memoro kiun vi volas.
Do se via programo kuras kaj vi volas entjero ekzekuto,
vi eble Mallock kvar bajtoj de memoro, malloc krampoj kvar.
>> Mallock trairos rigardanta tra la amaso,
ĉar ni estas dinamike asignante memoron,
kaj ĝi revenos al vi puntero al tiu memoro.
Ĝi ne donas al vi, ke memory-- ĝi ne donas al li nomon,
ĝi donas vin puntero al ĝi.
Kaj do jen kial mi denove diris ke gravas eble
maldormis la punteros video antaŭ ni ricevas tro multe en tiu.
Do malloc tuj donas vin reen montrilo.
>> Se Mallock ne povas doni al vi neniun memoro ĉar vi ne plu havas,
ĝi donos vin reen nula puntero.
Ĉu vi memoras kio okazas se ni provu dereference nula puntero?
Ni lasu seg kulpo, ĉu ne?
Tio probable ne bona.
>> Do ĉiufoje vi fari alvokon malloc vi ĉiam, ĉiam
bezonas kontroli ĉu la Pointer donis vin reen estas nula.
Se jes, vi devas fini vian programon ĉar se vi provas kaj dereference
la nula puntero vi tuj suferi segmentación kulpo
kaj via programo estas tuj frakasos ĉiuokaze.
Nu do kiel ni statike ricevi entjero?
>> int x.
Ni probable faris ke faskon da fojoj, dekstra?
Tio kreas variablon nomata x ke vivoj sur la stako.
Kiel ni dinamike ricevi entjero?
Mez stelo px egalas malloc 4.
>> Aŭ pli taŭge ni dirus int stelo px
egalas malloc grandeco de int, nur ĵeti iom malpli
magio nombroj ĉirkaŭ nia programo.
Tiu tuj akiri por ni kvar bajtoj de memoro de la amaso,
kaj la montrilon ni preni reen al ĝi estas nomita px.
Kaj subite ni havas faris antaŭe ni
povas dereference px al aliri tiu memoro.
Kiel ni akiras entjero de la uzanto?
Ni povas diri int x egalas atingi int.
Tio estas sufiĉe simpla.
Kio se ni volas krei tabelo de X kaleŝegoj kiuj vivas sur la pilo?
flosi stack_array-- jen la nomo de nia tabelo kvadrataj krampoj x.
Kiu kreos por ni tabelo de X kaleŝegoj kiuj vivas sur la stako.
Ni povas krei tabelon de kaleŝegoj kiu vivas sur la havaĵon, tro.
La sintakso povus aspekti iom pli ĝene,
sed ni povas diri kaleŝego stelo heap_array egalas
malloc x fojoj la grandeco de la kaleŝego.
Mi bezonas sufiĉan spacon por teni x glitpunktaj valoroj.
Do diras mi bezonas 100 kaleŝegoj, aŭ 1,000 kaleŝegoj.
Do en tiu kazo ĝi estus 400 bajtoj por 100 flosoj,
aŭ 4.000 bitokoj por 1,000 kaleŝegoj, ĉar ĉiu kaleŝego dissxutas
kvar bajtoj de spaco.
>> Post fari ĉi mi povas uzi la kvadrata krampo sintakso sur heap_array.
Ĝuste kiel mi farus en stack_array mi povas aliri lia elementoj individue
uzante heap_array nulo, heap_array unu.
Sed memoru la kialo ni povas fari tion Estas ĉar la nomo de tabelo en C
estas vere puntero tiu tabelo la unua elemento.
Do la fakto ke ni deklarante tabelo de kaleŝegoj sur la stako tie
Estas efektive iom misgvida.
Ni vere estas en la dua linio de kodo tie
ankaŭ kreante montrilon al eron de memoro kiun ni tiam fari iun laboron kun.
>> Jen la granda problemo kun dinamike asignita memoro kvankam,
kaj tio estas kial ĝi estas vere grave disvolvi kelkajn bonajn kutimojn
kiam vi laboras kun ĝi.
Kontraste statike deklaris memoro, via memoro
ne aŭtomate reiris al la sistemo kiam via funkcio estas farita.
Do se ni havas ĉefan, kaj ĉefa nomas funkcio
f, kiam f finas ajn ĝi estas faranta kaj resendas kontrolon de la programo
reen al ĉefa, ĉiuj la memoro ke f uzita estas redonita.
Ĝi povas esti uzita denove per iu alia programo,
aŭ alian funkcion kiu gets vokis poste sur en ĉefa.
Ĝi povas uzi tiun saman memoron denove.
>> Se vi dinamike rezervi memoron kvankam
vi devas eksplicite informi la sistemo kiu vi faris kun gxi.
Ĝi devos teni al ĝi por vi, kiuj povis konduki al problemo de vi elkuranta
de memoro.
Kaj fakte ni foje rilati al tiu kiel memoro liko.
Kaj kelkfoje tiuj memoro likas povas efektive esti vere devastador
por sistemo elfaro.
>> Se vi estas ofta uzanto de interreto vi povus uzi iujn foliumiloj,
kaj mi ne enoficigis nomojn tie, sed estas iuj foliumiloj tie
kiuj estas konataj por reale havi memoro likas ke ne get fiksita.
Kaj se vi lasas vian retumilon malfermita por tre longa periodo de tempo, tagoj
kaj tagoj, aŭ semajnoj, vi kelkfoje povus rimarki ke via sistemo
estas kurante vere, vere malrapide.
Kaj la kialo por tio estas ke la retumilo destinis memoro,
sed tiam ne rakontis la sistemo ke ĝi estas farita kun ĝi.
Kaj tial lasas malpli memoro disponebla por ĉiuj viaj aliaj programoj
devi dividi, ĉar vi estas leaking-- ke retumilo
programo estas likanta memoro.
Kiel ni donu memoron reen kiam ni el tio?
Nu, feliĉe ĝi estas tre facila maniero por fari ĝin.
Ni nur liberigi ĝin.
Ekzistas funkcio nomita libera, akceptas puntero al memoro,
kaj ni estas bone iri.
>> Do diru ni estas en la mezo de nia programo,
ni volas malloc 50 karakteroj.
Ni volas malloc tabelo kiu povas kapabla je posedo 50 karakteroj.
Kiam ni atingos montrilo reen al ke, ke puntero nomo estas vorto.
Ni faras tion, kion ni estas faros pri vorto,
kaj tiam kiam ni estas faris ni nur liberigi ĝin.
Nun ni revenis tiuj 50 bajtoj de memoro reen al la sistemo.
Iu alia funkcio povas uzi ilin.
Ni ne devas maltrankviligi suferi memoro liko ĉar ni liberigis vorto.
Ni donis la memoron reen, do ni faris laboranta kun ĝi.
Do estas tri oraj reguloj kiu devus
konservigxi en menso kiam vi estas dinamike asignante memoron
kun malloc.
Ĉiu bloko de memoro kiu vi malloc devas esti liberigita
antaŭ via programo finas kurante.
Nun ree, en la aparaton aŭ en la IDE ĉi tia okazas por vi ĉiuokaze
kiam you-- tio okazos ĉiuokaze kiam via programo estas finita,
tuta memoro estos liberigita.
Sed estas ĝenerale bona kodigo praktiko ĉiam, kiam vi faris,
liberigi kion vi mallocd.
>> Dirita, nur tion, kio vi havas mallocd devus esti liberigita.
Se vi statike deklaru entjero, int x duon-dupunkto,
kiu vivas sur la stako, vi ne tiam volis liberiĝi x.
Do nur aferojn kiuj vi havas mallocd devus esti liberigita.
>> Kaj laste, ne libera io dufoje.
Tio povas konduki al alian strangan situacion.
Do ĉio ke vi havas mallocd devas esti liberigitaj.
Nur aferojn kiuj vi havas malloc devus esti liberigita.
Kaj ne faras ion libera dufoje.
>> Do ni iru tra ekzemplo tie de kion iuj dinamike asignitaj
memoro povus aspekti miksita en iuj statika memoro.
Kio povus okazi tie?
Kontrolu cxu vi povas sekvi kune kaj diveni kio estas
okazos dum ni iras tra ĉiuj tiuj linioj de kodo.
>> Do ni diru int m.
Kio okazas ĉi tie?
Nu tiu estas bela simpla.
Mi kreas entjera variablo nomis m.
Mi kolora ĝi verdaj, ĉar tio estas la koloro
ke mi uzas kiam mi parolas pri entjeraj variabloj.
Ĝi estas skatolo.
Ĝi nomiĝas m, kaj vi povas vendejo entjeroj en ĝi.
>> Kio se mi tiam diri int stelo a?
Nu tio estas sufiĉe simila.
Mi kreas skatolon nomita.
Ĝi estas kapabla je posedo int steloj, punteros al entjeroj.
Do mi coloreando ĝi verda-ish tiel.
>> Mi scias ke ĝi havas ion fari kun entjero,
sed ĝi ne estas mem entjero.
Sed estas preskaux la sama ideo.
Mi kreis skatolo.
Ambaŭ pravas nun vivu sur la stako.
Mi donis ilin ambaŭ nomoj.
>> int stelo b egalas malloc grandeco de int.
Ĉi tiu povus esti iom malfacila.
Preni duan kaj pensi pri kio vi atendite okazi sur tiu diagramo.
int stelo b egalas malloc grandeco de int.
>> Nu tio ne nur krei unu skatolo.
Tiu fakte kreas du skatoloj.
Kaj ĝi ligas, ĝi ankaŭ establas punkto en interrilato.
Ni asignitaj unu bloko de memoro sur la havaĵon.
Rimarku ke la pinta dekstra skatolo tie ne havas nomon.
>> Ni mallocd ĝin.
Ekzistas sur la havaĵo.
Sed b havas nomon.
Ĝi estas puntero variablo nomis b.
Kiu vivas sur la stako.
>> Do ĝi estas peco de memoro kiu notas al alia.
b enhavas la adreson de tiu bloko de memoro.
Ĝi ne havas nomon alie.
Sed ĝi montras al ĝi.
Do kiam ni diras int stelo b egalas malloc grandeco de int, ke ĝuste tie,
ke sagon kiu pusxis supren sur la dekstra flanko, ke tuta afero,
Mi devos ĝin aperi denove, estas kio okazas.
Ĉiuj kiuj okazas en ke sola linio de kodo.
Nun ni ricevos iom pli rekta denove.
a egalas ampersand m.
Ĉu vi memoras kia egalas ampersand m estas?
Nu tio estas ricevas M adreso.
Aŭ meti pli diagrammatically, a punktoj al m.
>> a egalas b.
OK Do jen alia.
A egalas b.
Kio okazos al la diagramo tiun tempon?
>> Nu memoras ke la asigno operatoro verkoj
atribuante la valoro sur la rajton la valoro sur la maldekstra.
Do anstataŭ indikus m, nun notas al la sama loko ke b punktoj.
oni ne notas al B, A punktoj kie b punktoj.
>> Se pintan al b kiu volus estinti egalas ampersand b.
Sed anstataŭe egalas b simple signifas ke b estas nun
indikante la sama adreso, ĉar ene de b estas nur adreson.
Kaj nun ene de a estas la sama adreso.
m egalas 10, probable la plej simpla afero
ni jam faris en iomete.
Metu la 10 en la skatolo.
Stelo b egalas m plus 2, memoras de niajn punteros video kia stelo b signifas.
Ni tuj dereference b kaj meto iu valoro en tiu memoro loko.
En tiu kazo 12.
>> Do kiam ni dereference punkton de rememori ni nur vojaĝas malsupren sagoj.
Aŭ alia maniero, ni iri al tiu memoro Adreso
kaj ni manipuli ĝin iel.
Ni metu iu valoro en tie.
Tiukaze stelo b egalas m plus 2 estas simple
iri al la variablo indikis per b, iru al la memoro indikis per b,
kaj metis m plus 2 en tie, 12.
>> Nun liberto b.
Kio okazas kiam liberto b?
Memoru kion mi diris liberaj rimedoj.
Kion mi diris kiam liberto b?
>> Mi faritaj laboranta kun ĝi, ĉu ne?
Mi esence rezigni la memoro.
Mi donas ĝin al la sistemo.
Mi ne bezonas tiun anymore estas kion mi diras ilin, OK?
>> Nun se mi diras al stelo egalas 11 vi povas verŝajne
Jam diri ke io malbona okazos tie, ĉu ne?
Kaj efektive, se mi pretendas ke mi probable suferus segmentación kulpo.
Ĉar nun, kvankam antaŭe ke bloko de memoro
estis iu kiu mi havis aliro al, ĉe tiu punkto
nun mi aliranta memoro kiu ne leĝa por mi aliri.
>> Kaj kiel ni probable memoras, kiam ni aliras memoro
ke ni ne supozis tuŝi, tio estas la plej ofta kaŭzo
de segmentación kulpo. Kaj do mia programo
frakasus se mi provus fari tion.
Do denove estas bona ideo por akiri bonajn praktiko kaj bona kutimoj ekradikitaj
kiam laborante kun malloc kaj libera, por ke vi ne suferas segmentación
kulpoj, kaj ke vi uzas via dinamike asignitaj
memoro respondece.
>> Mi Doug Lloyd tiu estas CS50.