[Powered by Google Translate] [Kafli 5 - öruggari]
[Rob Bowden - Harvard University]
[Þetta er CS50. - CS50.TV]
>> Eins og ég sagði í tölvupósti mínum, there ert a einhver fjöldi af hlutur sem þú getur notað
annað en tæki til að raunverulega gera the vandamál setur.
Við mælum með að þú gera það í tækinu bara því þá geta fleiri auðveldlega hjálpað þér
og við vitum hvernig allt er að fara að vinna.
En eins og eitt dæmi um hvar þú getur gert það ef td þú hefur ekki aðgang
við tækið eða þú vilt vinna í miðju Science kjallara -
sem í raun þeir hafa tæki líka -
Ef þú vilt vinna hvar sem er.
Eitt dæmi er hefurðu séð / heyrt um SSH?
SSH er í grundvallaratriðum eins og tengja við eitthvað.
Reyndar, núna er ég SSHed í tækinu.
Ég vinn aldrei beint í tækið.
Hér er tæki, og ef þú lítur niður hér sjá þetta IP tölu.
Ég vinn aldrei í tækinu sjálfu,
Ég kem alltaf yfir til iTerm2 glugga / Terminal glugga.
Þú getur SSH til að þessi IP tölu, ssh jharvard@192.168.129.128.
Ég man að tala mjög auðveldlega því það er svo gott mynstur.
En það mun biðja mig um lykilorðið mitt, og nú er ég í tækið.
Í grundvallaratriðum, á þessum tímapunkti, ef þú opnað upp flugstöðinni inni á tækinu sjálfu,
þetta tengi, en þú vilt nota það, er nákvæmlega það sama
sem tengi ég nota hérna en nú þú ert SSHed.
Þú þarft ekki að SSH til að tækið.
Eitt dæmi um annan stað sem þú gætir SSH til er ég nokkuð viss um að þú ert með sjálfgefið -
Oh. Stærri.
Allt sem þú ættir að sjálfgefið FAS reikninga á FAS netþjónum.
Fyrir mig, myndi ég SSH til rbowden@nice.fas.harvard.edu.
Það er að fara að biðja þig um að í fyrsta skipti, og þú segir já.
Lykilorðið mitt er bara að fara að vera FAS lykilorðið mitt.
Og nú, er ég SSHed til ágætur netþjóna, og ég get gert hvað sem ég vil hér.
A einhver fjöldi af flokkum sem þú getur tekið, eins og 124, eru að fara að fá þig senda efni hingað
að í raun leggja vandamál setur þinn.
En að segja að þú hefur ekki aðgang að tækinu.
Þá er hægt að gera hlutina, eins og hér mun segja -
Þetta er bara hluti okkar spurningum.
Það mun biðja þig um að gera þetta í tækið.
Í stað þess að ég verð bara að gera það á þjóninum.
Ég ætla að renna niður það.
Vandamálið er að fara að vera að þú ert að nota til að nota eitthvað eins og gedit
eða hvað inni í tækinu.
Þú ert ekki að fara að hafa það á FAS miðlara.
Það er allt bara að fara að vera svona texta tengi.
Svo þú getur annaðhvort einn, reyna að læra texta ritil sem þeir hafa.
Þeir hafa Nano.
Nano er yfirleitt mjög auðvelt að nota.
Þú getur notað örvarnar og slá eðlilega.
Svo er það ekki erfitt.
Ef þú vilt fá virkilega fínt þú getur notað EmacsName,
sem ég líklega ætti ekki að hafa opnað vegna þess að ég veit ekki einu sinni hvernig á að loka EmacsName.
Control X, Control C? Já.
Eða þú getur notað vim, sem er það sem ég nota.
Og svo þá eru möguleikar þínir.
Ef þú vilt ekki að gera það, getur þú líka, ef þú lítur á manual.cs50.net--
Oh.
Á tölvu, getur þú SSH með kítti,
sem þú ert að fara að þurfa að sækja sérstaklega.
Á Mac, getur þú bara sjálfgefið nota Terminal eða þú getur sótt iTerm2,
sem er eins og a ágætur, fínt Terminal.
Ef þú ferð að manual.cs50.net þú munt sjá tengil á Notepad + +,
sem er það sem þú getur notað í tölvu.
Það gerir þér kleift að SFTP úr Notepad + +, sem er í grundvallaratriðum SSH.
Hvað þetta mun leyfa þér að gera er að breyta skrám á staðnum,
og þá alltaf þegar þú vilt spara þá, mun það spara til nice.fas,
þar sem þú getur þá keyrt þá.
Og samsvarandi á Mac er að fara að vera TextWrangler.
Svo gerir það þú gerir það sama.
Það leyfir þér að breyta skrám á staðnum og spara þá til nice.fas,
þar sem þú getur þá keyrt þá.
Svo ef þú ert alltaf fastur án tæki, hefur þú þessa valkosti
til enn gera vandamál setur þinn.
Eina vandamálið er að fara að vera að þú sért ekki að fara að hafa CS50 bókasafn
því nice.fas ekki sjálfgefið að hafa það.
Þú getur annað hvort að sækja CS50 bókasafn -
Ég held ekki að ég þarf að á þessum tímapunkti.
Þú getur annað hvort að sækja CS50 bókasafn og afrita það yfir til nice.fas,
eða ég held að á þessum tímapunkti sem við ekki nota það aftur hvort eð er.
Eða ef við gerum, getur þú um sinn skipta um það með
the gerð af hlutverkum í CS50 bókasafn samt.
Svo það ætti ekki að vera mikið takmarkana.
Og það er það.
>> Ég fer aftur í tækið núna, við munum gera allt sem í tækið.
Þegar litið er á hluta okkar spurningum í upphafi, eins og ég sagði í bréfinu mínu,
við verðum að tala um eitt stutt þú varst ætlað að horfa á.
Við höfum Áframsendi & Lagnir og þessar þrjár spurningar.
>> Sem streyma ekki virka eins og skrifa printf sjálfgefið?
Svo á. Hvað er straumur?
A straum er í grundvallaratriðum eins og það er bara -
Það er ekki einu sinni uppspretta 1s og 0s.
The Stream það er að biðja um hér er staðall út.
Og svo staðall út er læk að þegar þú skrifar á það,
það birtist á skjánum.
Standard út með á, þýðir það að þú skrifar bara 1s og 0s henni,
og hinum enda staðall út les bara úr því á.
Það er bara band af 1s og 0s.
Þú getur skrifað læki eða þú getur lesið úr lækjum
eftir hvaða straumi raunverulega er.
Hinir tveir vanræksla vatnsföll eru staðalbúnaður í og ​​staðall villa.
Standard í er þegar þú GetString, það er að bíða eftir þér að inntak efni.
Svo það að bíða eftir þér, það er í raun að bíða eftir staðall í,
sem er í raun það sem þú færð þegar þú skrifar á lyklaborðinu.
Þú ert að slá inn staðall tommu
Standard villa er í grundvallaratriðum jafngildir staðlaða út,
en það er sérhæft sig í að þegar þú hefur prentað út á staðlað villu úttak,
þú ert að ætlast til að aðeins prentað villa skilaboð til að
svo þú getur aðgreint milli reglulegra skilaboð prentuð á skjáinn
móti villa skilaboð eftir því hvort þeir fóru í venjulegt út eða staðalskekkja.
Skrá of.
Standard út staðall og staðall villa eru bara sérstakar læki,
en í raun allir skrá, þegar þú opnar skrá, verður það straum af bæti
þar sem þú getur bara lesið af þeim straumi.
Þú, að mestu leyti, get bara hugsa um skrá sem straum af bæti.
Svo streymir Hvað skrifa þeir við vanræksla? Standard út.
>> Hver er munurinn á milli> og >>?
Var einhver að horfa á vídeó áður? Allt í lagi.
> Er að fara að vera hvernig beina í skrá,
og >> er líka að fara að beina framleiðslu í skrá,
en það er í stað þess að fara að bæta við skrána.
Til dæmis, segjum að við skulum ég átt dict hérna,
og eina efni inni dict er köttur, köttur, hundur, fiskur, hundur.
Ein stjórn sem þú hefur á the stjórn lína er köttur,
sem er bara að fara að prenta það sem er í skránni.
Svo þegar ég segi köttur dict, það er að fara að prenta köttur, köttur, hundur, fiskur, hundur. Það er allt köttur gerir.
Það þýðir að það prentað til staðall út kött, köttur, hundur, fiskur, hundur.
Ef ég vil þess í stað að beina því að skrá, get ég notað> og áframsenda það til hvað skráin er.
Ég hringi í skrá skrá.
Svo nú ef ég LS, ég sjá að ég er með nýja skrá sem heitir skrá.
Og ef ég opna það upp, það er að fara að hafa nákvæmlega hvað köttur setja á stjórn lína.
Svo nú ef ég geri það aftur, þá er það að fara að beina framleiðslu í skrá,
og ég ætla að hafa sama nákvæmlega hlutur.
Svo tæknilega, overrode það alveg það sem við þurftum.
Og við munum sjá hvort ég breyti dict, tók ég út hundur.
Nú ef við köttur dict í skrá aftur, við erum að fara að hafa nýja útgáfu með fjarlægð hundur.
Svo kemur í það alveg það.
Staðinn, ef við notum >>, það er að fara til að bæta skrá.
Nú opna skrá, sjáum við að við höfum bara það sama prentuð tvisvar
vegna þess að það var það einu sinni, þá erum við bætt við upprunalega.
Hvað svo sem er> og >> gera.
Er næsta einn spyrja - Það er ekki að spyrja um það.
>> Hinn sem við höfum er að <, en ef> tilvísanir staðall út,
<Sé að fara að beina staðall inn
Við skulum sjá hvort við höfum dæmi.
Ég get skrifað einn raunverulegur fljótur.
Við skulum taka hvaða skrá, hello.c.
Tiltölulega einfalt skrá.
Ég ætla bara að fá band og prentun "Halló" hvað strengur ég kom var bara.
Svo gera halló og þá. / Halló.
Nú það vekur mig til að slá eitthvað,
sem þýðir að það er að bíða eftir hlutum til að koma inn í staðall tommu
Svo inn hvað sem ég vil í staðall inn Við erum bara að fara að segja Halló, Rob!
Þá er prentun staðall út Halló, Rob!
Ef ég geri. / Halló og þá beina,
að nú getur þú bara sent úr skrá.
Svo ef ég setti í sumum skrá, txt, og ég setti Rob,
ef ég hlaupa Halló og síðan beina skrá txt í. / halló, það er að fara að segja Halló, Rob! strax.
Þegar það gerist fyrst GetString og það er að bíða á lífskjörum í,
staðalbúnaður í er ekki lengur að bíða á lyklaborðinu fyrir gögn til að fá gert.
Þess í stað höfum við vísað staðall til að lesa úr skrá txt.
Og svo er að fara að lesa úr skrá txt, sem er bara línu Rob,
og þá það er að fara að prenta Hello, Rob!
Og ef ég vildi, gæti ég líka að gera. / Halló <txt
og þá staðall út að það er prentun, sem er Halló, Rob!,
Ég get sent það í eigin skrá sína.
Ég verð bara að hringja í skrá Halló - nei, ég mun ekki, því það er executable - txt2.
Nú txt2 er að fara að hafa úttak. / Hello <TXT, sem er að fara að vera Hello, Rob!
>> Spurningar?
>> Allt í lagi. Svo hér höfum við leiðsla.
Pípur eru síðustu eining utanáskrift.
>> Oh. Ég giska á einn eining utanáskrift er ef í stað þess að> þú 2>,
sem er Áframsendi staðalvillu.
Þannig að ef eitthvað fór í venjulegt villa, myndi það ekki að fá að setja inn txt2.
En taka ef ég 2>, þá er það samt prentun Hello, Rob! til the stjórn lína
vegna þess að ég er bara Áframsendi staðalvillu, ég er ekki Áframsendi staðall út.
Standard villa og staðall út eru öðruvísi.
Ef þú vilja til raunverulega skrifa staðall villa,
þá gæti ég breytt þessu til að vera fprintf til stderr.
Svo printf, við vanræksla, prentar við hefðbundna út.
Ef ég vil prenta staðall villa handvirkt, þá er ég að nota fprintf
og tilgreina það sem ég vil prenta út.
Ef í staðinn ég gerði fprintf stdout, þá er það í rauninni jafngild printf.
En fprintf við hefðbundna villu.
Svo nú, ef ég áframsenda þetta í txt2, Hello, Rob! er enn að fá prentuð á the stjórn lína
þar sem það er að fá prentað á venjulegt villa og ég er bara Áframsendi staðall út.
Ef ég beina nú staðall villa, nú var það ekki fá prentað, og txt2 er að fara að vera Hello, Rob!
Svo nú er hægt að prenta raunverulegum villur til staðall villa
og prenta reglulega skilaboð til staðlaða út.
Og svo þegar þú keyrir forritið, er hægt að keyra það eins og. / Hello þessa tegund með 2>
svo að kerfið þitt er að fara að keyra venjulega,
en allir villa skilaboð sem þú færð þér getur athugað síðar Innskráning villa þinn,
svo villur, og síðan leita seinna og villur skrá mun hafa einhverjar villur sem gerðist.
>> Spurningar?
>> Sú síðasta er pípa, sem hægt er að hugsa um eins og að taka staðalinn út frá einni stjórn
og gera það venjulegt í í næstu stjórn.
Dæmi hér er echo er a stjórn lína hlutur
það er bara að fara að echo hvað sem ég setti sem rök hennar. Ég mun ekki setja tilvitnanir.
Echo bla, bla, bla er bara að fara að prenta bla, bla, bla.
Áður, þegar ég sagði að ég þurfti að setja Rob í txt skrá
því ég get bara sent txt skrá, í stað, / ef ég echo Rob
og þá pípa það inn. / halló, það mun einnig gera the sami tegund af hlutur.
Þetta er að taka framleiðslugetu þessa skipun, echo Rob,
og nota það sem inntak fyrir. / Halló.
Þú getur hugsað um það sem fyrst beina echo Rob í skrá
og síðan inntak í. / Halló þessi skrá sem var bara outputted.
En það tekur tímabundna skrá úr myndinni.
>> Spurningar um það?
>> Næsta spurning er að fara að taka á þessu.
Hvaða leiðsla væri hægt að nota til að finna fjölda einstakra nöfn í skrá sem kallast names.txt?
Skipanir sem við erum að fara til að vilja nota hér eru einstök, svo Uniq og síðan wc.
Þú getur gert mann Uniq í raun líta á það sem það gerir,
og það er bara að fara að sía aðliggjandi samsvarandi línur af inntak.
Og maður wc er að fara að prenta newline, orð og bæti telja fyrir hverja skrá.
Og sá síðasti sem við erum að fara til að vilja nota er tegund,
sem er að fara að bara raða línur txt skrá.
Ef ég gera sumir txt skrá, names.txt, og það er Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob,
það sem ég vil gera hér er að finna fjölda einstakra nöfn í þessari skrá.
Svo hvað ætti svarið að vera? >> [Nemandi] 4. >> Já.
Það ætti að vera 4 frá Rob, Tommy, Jósef, eru RJ einu einstök nöfn í þessari skrá.
Fyrsta skrefið, ef ég geri bara orð telja á names.txt,
þetta er í raun að segja mér allt.
Þetta er í raun prentun - við skulum sjá, maður wc - newlines, orð og bæti telja.
Ef ég hugsa aðeins um línur, þá get ég bara gert wc-l names.txt.
Svo er það skref 1.
En ég vil ekki að wc-l names.txt því names.txt bara inniheldur öll nöfn,
og ég vil að sía út allir non-einstakt sjálfur.
Svo ef ég Uniq names.txt, sem er ekki alveg að gefa mér það sem ég vil
vegna þess að afrit nöfn eru enn þarna.
Hvers vegna er það? Hvers vegna er Uniq gera ekki það sem ég vil?
[Nemandi] The afrit eru ekki [inaudible] >> Já.
Mundu að maður síðu fyrir Uniq segir sía samliggjandi línur samsvörun.
Þeir eru ekki samliggjandi, þannig að það mun ekki sía þau.
Ef ég raða þeim fyrstu, flokka names.txt er að fara að setja öll afrit línur saman.
Svo nú er tegund names.txt það.
Ég ætla að vilja nota það sem inntak í Uniq, sem er | Uniq.
Það gefur mér Jósef, RJ, Rob, Tommy,
og ég vil nota það sem inntak í wc-l,
sem er að fara að gefa mér 4.
Eins og hér segir, hvaða leiðsla væri hægt að nota?
Þú geta gera a einhver fjöldi af hlutur eins og að nota röð af skipunum
þar sem þú ert að nota framleiðsla frá einum stjórn sem inntak í næstu stjórn.
Þú geta gera a einhver fjöldi af hlutur, fullt af snjöllum hlutum.
>> Spurningar?
Allt í lagi.
Það er það fyrir rör og utanáskrift.
>> Nú erum við að fara á til the raunverulegur efni, kóðun stuff.
Inni í þessu PDF sérðu þessa skipun,
og þú þarft að keyra þessa skipun í tækinu þínu.
wget er skipunin fyrir bara að fá eitthvað af internetinu, í grundvallaratriðum,
svo wget og þetta URL.
Ef þú fórst í þessa slóð í vafranum þínum, það myndi sækja þá skrá.
Ég smellti bara á það, svo það sótt skrána fyrir mig.
En skrifa wget af þessi hlutur inni í flugstöðinni
er bara að fara að sækja hana inn í flugstöðinni.
Ég hef section5.zip, og þú þarft að renna niður section5.zip,
sem er að fara að gefa þér möppu sem heitir section5,
sem er að fara að hafa allar skrár sem við erum að fara að vera með í dag inni í henni.
Eins og skrá nöfn þessara áætlana 'benda, eru þeir dálítið þrjótur,
svo er hlutverk þitt til að reikna út hvers vegna nota gdb.
Þurfa allir þá niður / vita hvernig á að sækja þá
í tæki þeirra? Allt í lagi.
>> Running ./buggy1, mun það segja Sundurliðun kenna (algerlega varpað),
sem hvenær þú færð segfault, er það slæmt.
Undir hvaða kringumstæðum þú færð segfault?
[Nemandi] Dereferencing núll músina. >> Já. Svo er það eitt dæmi.
Dereferencing núll músina sem þú ert að fara að fá segfault.
Hvað segfault þýðir er að þú ert að snerta minni sem þú ættir ekki að vera að snerta.
Svo dereferencing núll bendillinn er að snerta tölu 0,
og í rauninni segja allar tölvur nú á dögum að tölu 0 er minni sem þú ættir ekki að vera að snerta.
Svo er það hvers vegna dereferencing núll árangri músina í að segfault.
Þegar þú skyldir ekki frumstilla bendi, þá er það sorp gildi,
og svo þegar þú reynir að dereference það, að öllum líkindum þú ert að snerta minni
sem er í miðju hvergi.
Ef þú skyldir fá heppinn og sorp gildi
kom til að benda á einhvers staðar á mánudaginn eða eitthvað,
svo þegar þú dereference sem músina sem þú hefur ekki frumstilla,
ekkert mun fara úrskeiðis.
En ef það er að benda á, segja, einhvers staðar á milli stafla og hrúga,
eða það er að benda bara á eitthvað sem hefur ekki verið notuð af forritinu enn,
þá þú ert að snerta minni sem þú ættir ekki að vera að snerta og þú segfault.
Þegar þú skrifar endurkvæma virka og það recurses of oft
og stafla þitt vex of stór og stafla rekst inn í hlutina
að það ætti ekki að rekast á við, þú ert að snerta minni sem þú ættir ekki að vera að snerta,
svo þú segfault.
Það er það sem segfault er.
>> Það er einnig sama ástæða að ef þú hafa a band eins og -
við skulum fara aftur á fyrri áætlun.
Í hello.c--Ég er að fara bara að gera eitthvað annað.
char * s = "Halló heimur!";
Ef ég nota * s = eitthvað eða s [0] = 'X';
þannig að halló,. / halló, af hverju kom þessi segfault?
Hvers vegna var þetta segfault?
Hvað myndir þú búist við að gerast?
Ef ég gerði printf ("% s \ n", s), hvað myndir þú búast við að prenta?
[Nemandi] X Halló. >> Já.
Vandamálið er að þegar þú lýsa í band eins og þetta,
s er bendir sem er að fara á mánudaginn,
og hvað er að benda á er þetta band sem er að finna í lesa-eini minni.
Svo bara með nafninu, lesa-eini minni, ættir þú að fá hugmynd
að ef þú reynir að breyta því sem er hægt að lesa aðeins minni,
þú ert að gera eitthvað sem þú ættir ekki að vera að gera við minni og þú segfault.
Þetta er í raun stór munur char * s og char s [].
Svo bleikju s [], nú þetta band er að fara að setja á mánudaginn,
og stafla er ekki að lesa-eini, sem þýðir að það ætti að vinna fullkomlega fínn.
Og það gerir.
Mundu að þegar ég char * s = "Halló heimur!", S sig er á mánudaginn
en s benda til annars staðar, og að eitthvað annað gerist að lesa-eini.
En bleikju s [] er bara eitthvað á mánudaginn.
Svo er það annað dæmi um segfault gerast.
>> Við sáum að ./buggy1 leiddi til segfault.
Fræðilega séð, þá ættir þú ekki að líta á buggy1.c strax.
Þess í stað munum við líta á það í gegnum gdb.
Takið eftir að þegar þú færð Sundurliðun kenna (algerlega varpað),
þú færð þessa skrá hérna sem heitir algerlega.
Ef við LS-L, munum við sjá að algerlega er yfirleitt mjög stór skrá.
Þetta er fjöldi bæti á skrá, svo það lítur út eins og það er 250-eitthvað kílóbæti.
Ástæðan fyrir þessu er að það algerlega sorphaugur í raun er
er þegar program hrun, stöðu minni program
bara fær afrita og líma inn í þessa skrá.
Það verður varpað inn í þessi skrá.
Þetta forrit, á meðan það var í gangi, kom að minni notkun á um 250 kílóbæti,
og svo er það sem fékk varpað inn í þessa skrá.
Nú er hægt að líta á þessi skrá ef við gerum gdb buggy1 kjarna.
Við getum bara gert gdb buggy1, og það verður bara að byrja upp gdb reglulega,
nota buggy1 sem skrá inntak þess.
En ef þú gerir gdb buggy1 kjarna, þá er það sérstaklega að fara að byrja upp GDB
með því að horfa á þessi algerlega skrá.
Og þú að segja buggy1 þýðir gdb veit að það algerlega skrá kemur frá buggy1 program.
Svo gdb buggy1 algerlega er að fara að strax koma okkur
að þar sem kerfið varð að segja.
Við sjáum hér Program slitið með merki 11, skiptingu kenna.
Við koma til að sjá línu samkoma, sem sennilega er ekki mjög gagnlegt.
En ef þú skrifar BT eða rakningarskýrslu, sem er að fara til vera the fall
sem gefur okkur lista yfir núverandi stafla okkar ramma.
Svo aftur keyrslu. Það lítur út eins og við höfum aðeins tvær stakkur ramma.
Í fyrsta lagi er helsta stafla ramma okkar,
og annað er stafla ramma fyrir þessa aðgerð sem við verður að vera í,
sem lítur út eins og við höfum aðeins samkoma kóða fyrir.
Svo við skulum fara aftur til meginvirkni okkar,
og til að gera það sem við getum gert ramma 1, og ég held að við getum líka gert niður,
en ég næstum aldrei að gera niður - eða upp. Já.
Upp og niður. Upp koma þér upp einn stafla ramma, niður færir þig niður stafla ramma.
ÉG hafa tilhneigingu til að aldrei nota það.
Ég bara sérstaklega segja ramma 1, sem er að fara í ramma merkt 1.
Rammi 1 er að fara að koma okkur inn í helstu stafla ramma,
og það segir hér línu af kóða sem við verður að vera á.
Ef við vildum nokkrar fleiri línur af kóða, getum við sagt lista,
og það er að fara að gefa okkur allar línur af kóða í kringum það.
Línan við segfaulted á var 6:
if (strcmp ("CS50 björg", argv [1]) == 0).
Ef það er ekki augljóst enn, hægt að fá það beint frá hér bara með því að hugsa hvers vegna það segfaulted.
En við getum tekið það einu skrefi lengra og segja: "Hvers vegna vildi argv [1] segfault?"
Prenta skulum argv [1], og það lítur út eins og 0x0 það er, sem er null músina.
Við erum strcmping CS50 steina og núll, og svo er að fara að segfault.
Og hvers vegna er argv [1] null?
[Nemandi] Þar sem við ekki gefa það allir stjórn-lína rök.
Já. Við vildum ekki gefa það allir stjórn-lína rök.
Svo ./buggy1 er bara að fara að hafa argv [0] er ./buggy1.
Það er ekki að fara að hafa argv [1], svo það er að fara að segfault.
En ef í stað, ég bara CS50, það er að fara að segja að þú færð D
því það er það sem það er að gera.
Þegar litið er á buggy1.c, það er ætlast til að prenta "Þú færð D" -
Ef argv [1] er ekki "CS50 björg", "Þú færð D", annars "Þú færð A!"
Þannig að ef við viljum að A, við þurfum þetta til að bera saman eins og sannur,
sem þýðir að það jafnast á 0.
Svo argv [1] þarf að vera "CS50 steina".
Ef þú vilt gera það á the stjórn lína, þú þarft að nota \ að flýja rúm.
Svo CS50 \ björg og þú færð a!
Ef þú gera ekki sviga, af hverju virkar þetta ekki?
[Nemandi] Það er tvö mismunandi rök. >> Já.
Argv [1] er að fara að vera CS50 og argv [2] er að fara að vera björg. Allt í lagi.
>> Nú ./buggy2 er að fara að segfault aftur.
Í stað þess að opna það með skrá kjarna þess, munum við bara að opna buggy2 beint,
svo gdb buggy2.
Nú ef við hlaupum bara kerfi okkar, svo það er að fara að segja Program merkið SIGSEGV,
sem er segfault merki, og þetta er þar sem það gerðist að gerast.
Þegar litið er á rakningarskýrslu okkar, sjáum við að við vorum í aðgerðina oh_no,
sem var kallað eftir virka Dinky, sem hét af virka binky,
sem var kölluð helsta.
Við getum einnig séð rök að þessar aðgerðir.
Þau rök að Dinky og binky var 1.
Ef við lista virka oh_no, sjáum við að oh_no er bara að gera bleikju ** S = null;
* S = "Boom";
Hvers vegna vildi að mistakast?
[Nemandi] Þú getur ekki dereference núll músina? >> Já.
Þetta er bara að segja s er NULL, án tillits til hvort það gerist að vera bleikju **,
sem, eftir því hvernig þú túlka það, gæti það verið vísir að bendi á streng
eða fylki af strengjum.
Það er s er NULL, svo * s er dereferencing núll músina,
og svo þetta er að fara að hrun.
Þetta er einn af þeim hraða leiðir sem þú getur hugsanlega segfault.
Það er bara að lýsa yfir núll músina og strax segfaulting.
Það er það sem oh_no er að gera.
Ef við förum upp einn ramma, þá erum við að fara að fá inn í aðgerð sem kallast oh_no.
Ég þarf að gera það niður.
Ef þú ekki inn skipun og þú högg bara inn aftur,
það verður bara að endurtaka fyrri stjórn sem þú hleypur.
Við erum í ramma 1.
Skráning þessum ramma, sjáum við hér er hlutverk okkar.
Þú getur högg lista aftur, eða þú getur gert lista 20 og það mun listi meira.
Fallið Dinky segir ef ég er 1, þá hátta the oh_no virka,
annars fara á slinky virka.
Og við vitum að ég er 1 því við koma til að sjá þig hér
að Dinky var kallað með rök 1.
Eða þú getur bara prenta ég og það mun segja að ég er 1.
Við erum nú í Dinky, og ef við förum upp annan ramma, við vitum að við munum enda í binky.
Up. Nú erum við í binky.
Skráning þessa aðgerð - listi frá því fyrir helmingur skera mig burt -
það byrjaði eins og ég er 0, þá erum við að fara að kalla það oh_no, annars kalla Dinky.
Við vitum að ég var 1, þannig að það heitir Dinky.
Og nú erum við aftur í aðal og helstu er bara að fara að vera int i = rand ()% 3;
Það er bara að fara að gefa þér handahófi númer sem er annaðhvort 0, 1, eða 2.
Það er að fara að hringja binky við að tala, og það mun skila 0.
Þegar litið er á þetta,
bara ganga í gegnum forritið handvirkt án þess að keyra það strax,
þú vildi setja brjóta lið á Main, sem þýðir að þegar við hlaupa the program
program keyrir upp fyrr en það hits brjóta lið.
Svo keyra forrit, mun það hlaupa og þá mun það högg helstu hlutverk og hætta að birtast.
Nú erum við inni í helstu, og skref eða næsta er að fara að koma okkur í næstu línu af kóða.
Þú getur gert skref eða næsta.
Hitting næst, nú i hefur verið stillt á rand ()% 3, svo við getum prentað gildi i,
og það mun segja að ég er 1.
Nú er það spurning hvort við notum næst eða skref.
Ég giska á það máli í fyrri, en við myndum vilja að nota næst.
Ef við notum skref við stíga inn í aðgerð, sem þýðir líta á the raunverulegur hlutur
sem er að gerast inni í binky.
Ef við notum næst, þá þýðir það að fara yfir aðgerðina
og bara fara í næstu línu af kóða í meginvirkni okkar.
Hérna á þessari línu, ég var á þar sem það sagði rand ()% 3;
ef ég gerði skref, myndi það fara í framkvæmd Rand
og líta á hvað er að gerast þarna, og ég gat stíga gegnum Rand virka.
En ég er alveg sama um Rand virka.
Ég vil bara fara í næstu línu af kóða í helstu, svo ég nota næst.
En nú ég er alveg sama um binky virka, þannig að ég vil að stíga inn í það.
Nú er ég í binky.
Fyrsta lína af kóða er að fara að segja ef (i == 0), ég tek skref,
sjáum við á endanum á Dinky.
Ef við lista það, sjáum við að það athuga sé i = 0.
Ég er ekki jafn 0, svo það fór að annað ástand,
sem er að fara að hringja Dinky (i).
Þú gætir fengið ráðvilltur.
Ef þú horfir bara á þessar línur beint, þú might hugsa ef (i == 0),
allt í lagi, svo ég tók skref og nú er ég á Dinky (i),
þú might hugsa þessi að meina i = 0 eða eitthvað.
Nei, það þýðir bara að það veit að það getur standa beint á línuna Dinky (i).
Þar sem ég er ekki 0, næsta skref er ekki að fara að enda í annað.
Annars er ekki lína og það er að fara að hætta á.
Það er bara að fara að fara í næstu línu og það getur raunverulega framkvæma, sem er Dinky (i).
Stepping í Dinky (i), sjáum við ef (i == 1).
Við vitum i = 1, þannig að þegar við stíga, við vitum að við erum að fara að enda í oh_no
því i = 1 kallar virka oh_no, sem hægt er að flytja,
sem er að fara að setja bleikju ** s = til NÚLL og strax "Boom".
Og þá í raun að líta á framkvæmd buggy2,
þetta er ég bara að fá handahófi númerið - 0, 1, eða 2 - starf binky,
sem ef ég er 0 kallar oh_no, annar kallar það Dinky, sem kemur upp hérna.
Ef ég er 1, kalla oh_no, annars kalla slinky, sem koma upp hér,
ef ég er 2, kalla oh_no.
Ég er ekki einu sinni hugsa það er a vegur -
Hefur einhver séð leið til að gera þetta forrit sem vilja ekki segfault?
Vegna nema ég vantar eitthvað, ef ég er 0, munt þú strax segfault,
annars þú ferð að aðgerð sem ef ég er 1 að segfault,
annað sem þú ferð í aðgerð þar sem ef ég er 2 sem þú segfault.
Svo er sama hvað þú gerir, segfault þér.
>> Ætli eina leiðin til að ákveða að það væri í stað þess að gera bleikju ** S = NULL,
þú gætir malloc pláss fyrir það band.
Við gætum gert malloc (sizeof) - sizeof hvað?
[Nemandi] (char) * 5? >> Er þetta að vera sanngjarnt?
Ég er hrokafullur þetta mun virka ef ég hljóp í raun það, en það er ekki það sem ég er að leita að.
Horfðu á hvaða s. Við skulum bæta við int *, svo int * x.
Ég myndi gera malloc (sizeof (int)).
Eða ef ég vildi fjölda 5, myndi ég gera (sizeof (int) * 5);
Hvað ef ég hef int **?
Hvað myndi ég malloc?
[Nemandi] Stærð músina. >> Já. (Sizeof (int *));
Sami hlutur hér niðri.
Ég vil (sizeof (char *));
Þetta er að fara að úthluta pláss fyrir músina sem bendir til "búmm".
Ég þarf ekki að úthluta pláss fyrir "uppsveiflu" sig
vegna þess að þetta er í grundvallaratriðum jafngildir það sem ég sagði áður
á char * x = "Boom".
"Boom" er þegar til. Það gerist að vera til í lesa-eini svæði minni.
En það er nú þegar, sem þýðir þessa línu af kóða, ef s er bleikju **,
þá er * s a char * og þú ert að setja þetta char * að benda á "uppgangs".
Ef ég vildi til að afrita "Boom" í S, þá myndi ég þurfa að úthluta pláss fyrir s.
Ég skal gera * s = malloc (sizeof (char) * 5);
Hvers vegna 5?
Af hverju ekki 4? Það lítur út eins og "Boom" er 4 stafir. >> [Nemandi] The null staf.
Já. Allar strengi eru að fara að þurfa að núll staf.
Nú get ég gert eitthvað eins strcat - Hvað er að virka til að afrita streng?
[Nemandi] cpy? >> Strcpy.
maður strcpy.
Svo strcpy eða strncpy.
strncpy er aðeins öruggari þar sem þú getur tilgreint nákvæmlega hversu margir stafir,
en hér er það skiptir ekki máli vegna þess að við vitum.
Svo strcpy og líta á rökin.
Fyrsta röksemd er áfangastaður okkar.
Seinni rök er uppspretta okkar.
Við ætlum að afrita í * áfangastað okkar s bendillinn "Boom".
Hvers vegna þú vilt kannski að gera þetta með strcpy stað það sem við áttum áður
á * s = "Boom"?
Það er ástæða þú might vilja til að gera þetta, en hvað er það ástæðan?
[Nemandi] Ef þú vilt breyta einhverju í "búmm". >> Já.
Nú get ég gert eitthvað eins og S [0] = 'X';
því s bendir á vörðu og að rúm á hrúga sem s bendir til
er bendi til fleiri pláss á hrúga, sem geyma "búmm".
Svo þetta eintak af "búmm" er geymd í hrúga.
Það eru tæknilega tvö eintök af "búmm" í kerfinu okkar.
Það er sú fyrsta sem er bara gefið þetta "Boom" band stöðug,
og annað eintak af "búmm", strcpy skapaði afrit af "búmm".
En afrit af "búmm" er geymt á hrúga og hrúga sem þú ert frjáls til að breyta.
Hrúga er ekki að lesa-eini, svo það þýðir að s [0]
er að fara að láta þig breyta gildi "búmm".
Það er að fara að láta þig breyta þeim stafi.
>> Spurningar?
Allt í lagi.
>> Að flytja til buggy3 skulum gdb buggy3.
Við hlaupa bara og við sjáum að við fá segfault.
Ef við aftur keyrslu, þá eru aðeins tvær aðgerðir.
Ef við förum upp í meginvirkni okkar, sjáum við að við segfaulted á þessari línu.
Svo bara horfa á þessa línu, fyrir (INT línu = 0; fgets þetta efni er ekki jafn null;
lína + +).
Fyrri ramminn okkar var kölluð _IO_fgets.
Þú munt sjá að mikið með innbyggðum C aðgerðir,
að þegar þú færð að segfault, það verður mjög Cryptic virka nöfn
eins og þetta _IO_fgets.
En það er að fara að tengja við þessa fgets símtali.
Einhvers staðar inni hér, við erum segfaulting.
Ef við skoðum rök til fgets, getum við prentað biðminni.
Skulum prenta sem - Ó, nei.
Print er ekki að fara að vinna nákvæmlega eins og ég vil það til.
Við skulum líta á the raunverulegur program.
Buffer er eðli array. Það er eðli array af 128 stöfum.
Svo þegar ég segi prenta biðminni, það er að fara að prenta þessa 128 stafi,
sem ég giska á er það er gert ráð fyrir.
Það sem ég var að leita að er að prenta heimilisfang biðminni,
en það er í raun ekki segja mér mikið.
Svo þegar ég koma að segja upp hérna x biðminni, sýnir það mér 0xbffff090,
sem, ef þú manst frá fyrri eða einhverjum tímapunkti, Oxbffff tilhneigingu til að vera stafla-ish svæði.
The stakkur hefur tilhneigingu til að byrja einhvers staðar rétt undir 0xc000.
Bara með því að sjá þessa tölu, ég veit að biðminni er að gerast á mánudaginn.
Ræsa á ný áætlun mína, hlaupa, upp, biðminni við sáum var þessi röð af stöfum
sem eru nánast tilgangslaust.
Þá prentun skrá, það er skrá út?
[Nemandi] null. >> Já.
Skrá er um skrá tegund *, svo það er bendillinn,
og gildi þess bendillinn er null.
Svo fgets er að fara að reyna að lesa úr þeim músina með óbeinum hætti,
en í því skyni að fá aðgang að músina, það hefur til dereference það.
Eða, til að komast það sem það ætti að vera að benda á, það dereferences hana.
Svo það er dereferencing núll músina og það segfaults.
Ég hefði getað endurræst hana þar.
Ef við brot á aðalatriði okkar og keyra,
fyrsta lína af kóða er char * skráarheiti = "nonexistent.txt";
Það ætti að gefa nokkuð stór vísbending um hvers vegna þetta forrit ekki.
Vélritun næst kemur mér í næstu línu, þar sem ég opna þessa skrá,
og þá fæ ég strax í línu okkar, þar sem þegar ég högg næst, það er að fara að segfault.
Er einhver sem vill til að henda út ástæðu hvers vegna við gætum verið segfaulting?
[Nemandi] Skráin er ekki til. >> Já.
Þetta er ætlað að vera vísbending
að þegar þú ert að opna skrána sem þú þarft að athuga að skrá raunverulega til.
Svo hér, "nonexistent.txt";
Þegar við fopen skráarheiti fyrir lestur, þurfum við þá að segja
if (skrá == NULL) og segja printf ("Skráin er ekki til!"
eða - enn betra - filename), skila 1;
Svo nú erum við að athuga hvort það er NULL
áður en þeir halda áfram og reyna að lesa úr þeirri skrá.
Við getum endurgerð það bara til að sjá að það virkar.
Ég ætlaði að setja nýja línu.
Svo nú nonexistent.txt er ekki til.
Þú ættir alltaf að leita að þessari tegund af hlutur.
Þú ættir alltaf að athuga hvort fopen skilar NULL.
Þú ættir alltaf að ganga úr skugga um að malloc ekki aftur núll,
eða annað sem þú segfault.
>> Nú buggy4.c.
Gangi. Ég giska á það er að bíða fyrir hjálpina eða hugsanlega óendanlega lykkja.
Já, það er óendanlega lykkja.
Svo buggy4. Það lítur út eins og við erum óendanlega lykkja.
Við getum skemmt á helstu, hlaupa program okkar.
Í gdb, svo lengi sem skammstöfun sem þú notar er ótvíræð
eða sérstakar skammstafanir sem þeir kveða á um þig,
þá er hægt að nota n til að nota næst í stað þess að þurfa að slá út næsta alla leið.
Og núna þegar ég hef högg N einu sinni, get ég bara á Enter til að halda áfram á næsta
stað þess að þurfa að lemja N Enter, n inn, n inn.
Það lítur út eins og ég er í einhvers konar fyrir lykkju sem er stilling array [i] í 0.
Það lítur út eins og ég er aldrei að brjóta út af þessu til hliðar.
Ef ég prenta ég, svo ég er 2, svo ég ætla að fara næst.
Ég prenta ég, ég er 3, þá fer ég næst.
Ég prenta ég og ég er 3. Næst, prenta ég, er i 4.
Reyndar, prenta sizeof (array), svo stærð array er 20.
En það lítur út eins og það er einhver sérstakur gdb stjórn til að fara þangað til eitthvað gerist.
Það er eins og að setja upp ástand á gildi breytu. En ég man ekki hvað það er.
Svo ef við höldum að fara -
Hvað varstu að segja? Hvað gerðir þú koma upp?
[Nemandi] er sýna i bætt - >> Já. Svo sýna að ég get hjálpað.
Ef við sýna bara ég, það mun setja upp hér hvaða gildi ég er
þannig að ég þarf ekki að prenta það út í hvert skipti.
Ef við höldum bara að fara næst, sjáum við 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5.
Eitthvað er að fara hræðilega rangt, og ég er að endurstilla til 0.
Þegar litið er á buggy4.c, sjáum við allt sem gerist er int array [5];
fyrir (i = 0; i <= sizeof (array), i + +)
array [i] = 0;
Hvað sjáum við að er rangt hérna?
Sem vott, þegar ég var að gera á gdb buggy4 - við skulum brjóta helstu, hlaupa -
Ég gerði prenta sizeof (array) bara til að sjá hvað ástand er þar sem ég ætti að lokum brjótast út.
Hvar er ég? Sagði ég að keyra?
Ég vissi ekki að lýsa enn.
Svo prenta sizeof (array) og það er 20,
sem er gert ráð fyrir því array minn er stærð 5 og það er af 5 heiltölur
þannig að allt sem ætti að vera 5 * sizeof (int) bæti, þar sizeof (int) tilhneigingu til að vera 4.
Svo sizeof (array) 20.
Hvað ætti þetta að vera?
[Nemandi] deilt með sizeof (int). >> Já, / sizeof (int).
Það lítur út eins og það er enn vandamál hér. Ég held að þetta ætti bara að vera <
þar sem það er ansi mikið alltaf <og aldrei <=.
Nú skulum hugsa um það hvers vegna þetta var í raun brotin.
Hefur einhver hafa gátur af hverju var ég að endurstilla til 0 gegnum hverja endurtekning á henni?
Það eina inni hér sem er að gerast er að array [i] er stillt á 0.
Svo einhvern veginn, þessi lína af kóða veldur int okkar i að vera stillt á 0.
[Nemandi] Gæti það verið vegna þess að það er að vega þyngra á minni þessa hluta i
þegar það telur að það er næsta þáttur fylki? >> [Bowden] Já.
Þegar við erum að fara út í lok array okkar,
einhvern veginn að rými sem við erum ríkari að vega þyngra gildi i.
Og svo ef við skoðum í buggy4, brjóta helstu Run
skulum prenta heimilisfang i.
Það lítur út eins og það er bffff124.
Nú skulum prenta heimilisfang array [0]. 110.
Hvað um [1]? 114.
[2], 118.
11C, 120. array [5] er bfff124.
Svo array [5] hefur sama heimilisfang og ég, sem þýðir að array [5] er ég.
Ef þeir hafa sama heimilisfang, eru þau það sama.
Svo þegar við setjum array [5] til 0, við erum að setja i í 0.
Og ef þér finnst um þetta í skilmálum á mánudaginn,
int i er lýst fyrst, sem þýðir að ég fær pláss á mánudaginn.
Þá array [5] er úthlutað, svo þá 20 bæti eru úthlutað á mánudaginn.
Svo ég fær úthlutað fyrst, þá eru þessir 20 bytes fá úthlutað.
Svo gerist ég rétt fyrir fylking,
og vegna þess hvernig, eins og ég sagði í síðustu viku, þar sem tæknilega vex stafla niður,
þegar vísitalan í fylki, við erum tryggð að 0 stöðu í fylkinu
alltaf gerist fyrir efstu stöðu í fylking.
Þetta er góður af því hvernig ég dró hana í síðustu viku.
Takið eftir því að neðst við höfum heimilisfang 0 og efst við höfum heimilisfang Max.
The stakkur er alltaf að vaxa niður.
Við skulum segja að við úthluta i.
Við úthluta heiltala i, sem þýðir við skulum bara segja að hér heiltala i fær úthlutað.
Þá erum við að úthluta fjölda okkar 5 heiltölur, sem þýðir að undir því,
þar sem stakkur er að vaxa niður, fá þeir 5 heiltölur úthlutað.
En vegna þess hvernig fylki vinna, erum við að tryggja að fyrsta staða í fylkinu
alltaf hefur heimilisfang minna en seinni hlutur í fylki.
Svo hefur array stöðu 0 alltaf að gerast fyrst í minni,
en array stöðu 1 hefur að gerast eftir það
og fylki stöðu 2 að gerast eftir það,
sem þýðir að staða array 0 myndi gerast einhvers staðar hérna,
array stöðu 1 myndi gerast yfir þessi
því að færa upp þýðir hærri tölur þar sem hámark netfang er upp hér.
Svo array [0] hérna, array [1] hérna, array [2] upp hér, array [3] upp hér.
Taktu eftir hvernig áður en við úthlutað heiltölu i alla leið upp hér,
eins og við flutt lengra og lengra inn í array okkar, við erum að fá nær og nær að heiltala okkar i.
Það gerist bara svo að array [5], sem er ein staða utan array okkar,
er einmitt þar sem heiltala Ég varð að vera úthlutað.
Svo er það málið þar sem við verður að vera hitting pláss á stafla
sem var úthlutað fyrir heiltölu i, og við erum að setja það í 0.
>> Það er hvernig það virkar. Spurningar? Já.
[Nemandi] Aldrei hugur. Allt í lagi.
[Nemandi] Hvernig forðast þér þessar konar villur?
Þessi tegund af villa? Ekki nota C sem tungumál forritun.
Nota tungumál sem hefur array mörk stöðva.
Svo lengi sem þú ert varkár, þú þarft bara að koma í veg fyrir að fara framhjá mörk array þínu.
[Nemandi] Svo hér þegar við fórum framhjá mörk array þínu -
[Bowden] Það er þar sem hlutirnir byrja að fara úrskeiðis. >> [Nemandi] Ó, allt í lagi.
Svo lengi sem þú dvelur í minni úthlutað fyrir array þinn, þú ert fínn.
En C er ekki villa stöðva. Ef ég array [1000], mun það gjarna bara breyta hvað gerist -
Það fer í byrjun fylkisins, þá fer 1000 stöðum eftir og setur það í 0.
Það skiptir ekki gera allir stöðva sem ó, þetta er ekki í raun að hafa 1000 hlutina í það.
1000 er vegur yfir það sem ég ætti að breyta,
en Java eða eitthvað sem þú munt fá array utan marka vísitölu
eða vísitölu út af mörk undantekning.
Það er hvers vegna a einhver fjöldi af meiri tungumál hafa þetta
þar sem ef þú ferð út fyrir mörk í fylkinu, ekki þú
þannig að þú getur ekki breytt hlutum undan þér
og svo hlutirnir fara miklu verri en bara að fá undantekningu
segja að þú fórst út í lok fylkisins.
[Nemandi] Og svo að við höfum bara breytt <= bara <? >> [Bowden] Já.
Það ætti að vera <sizeof (array) / sizeof (int);
þar sizeof (array) er 20, en við viljum aðeins 5. >> [Nemandi] Rétt.
Fleiri spurningar? Allt í lagi.
>> [Nemandi] Ég er með spurningu. >> Já.
[Nemandi] Hvað er í raun fylki breytu?
[Bowden] Eins hvað er fylki?
Array sjálft er tákn.
Það er bara heimilisfang the byrjun af the 20 bæti sem við erum að vísa.
Þú getur hugsað um það sem bendill, en það er stöðug músina.
Um leið og hlutirnir fá saman, breytu array er ekki til lengur.
[Nemandi] Svo hvernig er það að finna stærð fylkisins?
Stærð fylkisins er átt við stærð sem hindra að þessi tákn vísar til.
Þegar ég gera eitthvað eins og printf ("% p \ n", array);
skulum hlaupa það.
Hvað gerði ég bara rangt?
'Array "Array lýst hér.
Ó, allt hér.
Clang er sniðug, og það gerist að taka eftir að ég lýsti array sem 5 atriði
en ég er að flokkun í stöðu 1000.
Það er hægt að gera það vegna þess að þetta eru bara fastar.
Það getur einungis farið svo langt í að taka eftir því að ég er að fara út fyrir mörk í fylki.
En taka fyrir þegar við átti ég að vera rangt,
það getur ekki hugsanlega að ákvarða hversu mörg gildi ég gæti tekið á,
svo það er ekki hægt að ákveða að ég var að fara út í lok fylkisins.
Það er bara Clang vera snjall.
>> En nú gera buggy4. Svo hvað er ég að gera rangt?
Óbeint lýsa bókasafn virka 'printf ".
Ég ætla að vilja # include .
Allt í lagi. Nú keyra buggy4.
Prentun gildi fylkisins eins og ég gerði hér, prenta það sem bendillinn
prenta eitthvað sem lítur út eins og þetta - bfb8805c - sem er einhver netfang
sem er í stafla-ish svæðinu.
Array sjálft er eins og músina, en það er ekki raunverulegt músina,
síðan reglulega músina við getum breytt.
Array er bara fasti. The 20 blokkir af minni byrja á 0xbfb8805c heimilisfang.
Svo bfb8805c gegnum þetta netfang +20--eða ég giska á -20 -
er allt af minni úthlutað fyrir þetta fylki.
Array er breytu sig ekki geymt hvar.
Þegar þú ert að setja saman, er þýðandi - hönd veifa á það -
en þýðandinn verður bara að nota þar sem það veit array að vera.
Það veit hvar það array byrjar,
og svo það er alltaf hægt að bara gera það með tilliti til uppbóta frá því upphafi.
Það þarf ekki að breyta sjálfu sér að tákna fjölda.
En þegar ég geri eitthvað eins og int * p = array, nú p er bendir sem bendir til þess fjölda,
og nú p raunverulega er til staðar á mánudaginn.
Ég er frjáls til að breyta bls. Ég get gert p = malloc.
Svo það benti upphaflega fylkisins, en nú bendir það til pláss á hrúga.
Ég get ekki gert array = malloc.
Ef Clang er snjall, það mun öskra á mig strax the kylfa.
Reyndar er ég nokkuð viss gcc myndi gera þetta líka.
Svo array type "int [5] 'er ekki framseljanlegur.
Þú getur ekki framselt eitthvað til array tegund
því fylki er bara fasti.
Það er tákn sem tilvísanir þá 20 bæti. Ég get ekki breytt því.
>> [Nemandi] Og hvar er stærð fylkisins geymdar?
[Bowden] Það er ekki geymt hvar. Það er þegar það er að setja saman.
Svo hvar er stærð fylkisins geymdar?
Þú getur aðeins notað sizeof (array) innan virka sem array er lýst sig.
Svo ef ég gera sumir virka, Foo, og ég (int array [])
printf ("% d \ n", sizeof (array));
og svo niður ég kalla foo (array);
innan þessa virka - við skulum hlaupa það.
Þetta er Clang vera snjall aftur.
Það er að segja mér að sizeof á array virka breytu
mun skila stærð 'int *'.
Þetta væri villa ef það er ekki það sem ég vildi að gerast.
Við skulum í raun slökkva Werror.
Aðvörun. Viðvaranir eru í lagi.
Það mun samt saman eins lengi og það hefur viðvörun.
. / A.out er að fara að prenta 4.
The viðvörun sem var búin til er skýr vísbending um hvað fór úrskeiðis.
Þetta int array er bara að fara að prenta sizeof (int *).
Jafnvel ef ég setja array [5] hér, það er samt bara að fara að prenta sizeof (int *).
Svo um leið og þú að gefa það í aðgerð, greinarmun á milli fylki og ábendingum
er engin.
Þetta gerist að vera fylki sem var lýst á mánudaginn,
en um leið og við fara að gildi, að 0xbf bla, bla, bla í þessa aðgerð,
þá bendir þetta bendi til að fylki á mánudaginn.
Svo þýðir að sizeof aðeins við í aðgerð sem fylki var lýst,
sem þýðir að þegar þú ert að setja saman þessa aðgerð,
þegar Clang fer í gegnum þessa aðgerð, sér það fylki er int fylki af stærð 5.
Svo það sér sizeof (array). Jæja, það er 20.
Það er í raun hvernig sizeof grundvallaratriðum virkar fyrir næstum öllum tilvikum.
Sizeof er ekki fall, það er rekstraraðili.
Þú kalla ekki sizeof virka.
Sizeof (int), sem þýðandi verður bara þýða það að 4.
Fattarðu? Allt í lagi.
>> [Nemandi] Svo er það munurinn sizeof (array) í aðal og foo?
Þetta er vegna þess að við erum að segja sizeof (array), sem er af gerðinni int *,
en fylki niður er hér ekki gerð int *, það er int array.
>> [Nemandi] Þannig að ef þú hefðir breytu í array [] í stað int * fylkisins,
vildi að meina að þú gætir samt breytt array því nú er það bendi?
[Bowden] Eins og þetta? >> [Nemandi] Já. Getur þú breytt array innan virka núna?
[Bowden] Þú getur breytt fjölda í báðum tilvikum.
Í báðum þessum tilvikum sem þú ert frjáls til að segja array [4] = 0.
[Nemandi] En er hægt að gera array benda á eitthvað annað?
[Bowden] Ó. Já. Í báðum tilvikum - >> [nemandi] Já.
[Bowden] Munurinn array [] og int * array, það er enginn.
Þú getur einnig fá sumir fjölvíða fylki hér
fyrir sumir þægilegur setningafræði, en það er samt bara músina.
Þetta þýðir að ég er frjáls til að gera array = malloc (sizeof (int)), og nú benda eitthvað annað.
En bara eins og hvernig þetta virkar að eilífu og alltaf,
breyta þessu fylki með því að gera það benda til að eitthvað annað
ekki breyta array niður hér því það er afrit af rifrildi,
það er ekki músina til að rök.
Og í raun, rétt eins og fleiri vísbending um að það er nákvæmlega sama -
við sáum nú þegar hvað prentun array prentar -
hvað ef við prenta heimilisfang fylkisins eða heimilisfang heimilisfang fylkisins
annað hvort þeirra?
Skulum hunsa þessa.
Allt í lagi. Þetta er allt í lagi. Það er nú í gangi. / A.out.
Prentun array, þá prenta heimilisfang fylkisins, eru það sama.
Array bara er ekki til.
Það veit þegar þú ert prentun array, þú ert prentun á táknið sem er átt við þá 20 bæti.
Prentun veffang fylki, vel, fylki er ekki til.
Það hefur ekki netfang, þannig að hún prentar bara heimilisfang þessara 20 bæti.
Um leið og þú saman niður, eins og í unnin buggy4 þínu. / A.out,
array er engin.
Ábendingum til. Fylki ekki.
Blokkir af minni fulltrúar array til enn,
en breyta array og breytur í þeirri tegund ekki til.
Þeir eru eins og the aðalæð mismunur milli fylki og ábendingum
eru eins fljótt og þú gerir virka símtöl, það er engin munur.
En inni í aðgerð að array sig er lýst, sizeof virkar öðruvísi
þar sem þú ert að prenta stærð blokkir í stað stærðar tegund,
og þú getur ekki breytt því vegna þess að það er tákn.
Prentun þings og veffang hlutur prentar það sama.
Og það er ansi mikið það.
[Nemandi] Gætirðu sagt að einu sinni enn?
Ég gæti hafa misst eitthvað.
Prentun array og heimilisfang array prentar það sama,
en ef þú prenta bendi á móti heimilisfang músina,
sá hlutur prentar heimilisfang sem þú ert að benda á,
hinn prentar veffang bendill á mánudaginn.
Þú getur breytt músina, þú getur ekki breytt fylki tákn.
Og sizeof bendillinn er að fara að prenta stærð það músina tegund.
Svo int * p sizeof (p) er að fara að prenta 4,
en int array [5] prenta sizeof (array) er að fara að prenta 20.
[Nemandi] Svo int array [5] að prenta 20? >> Já.
Þess vegna innan buggy4 þegar það er notað til að vera sizeof (array)
þetta var að gera i <20, sem er ekki það sem við vildum.
Við viljum i <5. >> [Nemandi] lagi.
[Bowden] Og þá eins fljótt og þú byrjar farið í aðgerðir,
Ef við gerðum int * p = array;
inni á þessum eiginleika, getum við í rauninni að nota p og fylkið á nákvæmlega sama hátt,
nema fyrir sizeof vandamál og breyttum vandamál.
En p [0] = 1; er það sama og að segja array [0] = 1;
Og um leið og við segjum foo (array) eða foo (p);
inni á foo virka, þetta er sami hringja tvisvar.
Það er enginn munur á milli þessara tveggja símtala.
>> Allir vel á það? Allt í lagi.
Við höfum 10 mínútur.
>> Við munum reyna að komast í gegnum þetta Typer Hacker áætlun,
þetta vefsvæði, sem kom út á síðasta ári eða eitthvað.
Það er bara að vera eins og þú slærð af handahófi og það prentar út -
Whatever skrá það gerist að hafa hlaðinn er það sem það lítur út eins og þú ert að skrifa.
Það lítur út eins og einhvers konar stýrikerfi kóða.
Það er það sem við viljum framkvæma.
Þú ættir að hafa tvöfaldur executable heitir hacker_typer
sem tekur í einu rifrildi, sem skrá til "spjallþráð tegund."
Keyrir executable að hreinsa skjáinn
og síðan prentað út einn staf úr liðin-í skrá í hvert skipti sem notandi þrýsta á takka.
Svo hvað lykillinn að styðja á, það ætti að henda og í staðinn prenta staf af skrá
það er þau rök.
Ég nokkurn veginn hvað er það sem við erum að fara að þurfa að vita er.
En við viljum að kíkja á termios bókasafn.
Ég hef aldrei notað þetta bókasafn á minni ævi, svo það er mjög lítil tilgangi.
En þetta er að fara að vera bókasafn sem við getum notað til að henda til stafurinn sem þú högg
þegar þú ert að slá inn staðall tommu
Svo hacker_typer.c, og við erum að fara að vilja að # include .
Þegar litið er á manninn síðu í termios - Ég er giska flugstöðinni það er OS eða eitthvað -
Ég veit ekki hvernig á að lesa það.
Þegar litið er á þetta, segir það að fela þessar 2 skrár, þannig að við munum gera það.
>> Fyrstur hlutur fyrstur, viljum við taka í einu rifrildi, sem er skrá við ættum að opna.
Svo hvað vil ég gera? Hvernig athuga ég að sjá að ég er með einn rifrildi?
[Nemandi] Ef argc jafngildir það. >> [Bowden] Já.
Svo ef (argc = 2!) Printf ("Notkun:% s [skrá til að opna]").
Svo nú ef ég keyrt það án þess að veita annað rök - oh, þarf ég nýja línu -
þú munt sjá að það segir notkun:. / hacker_typer,
og þá seinni röksemd ætti að vera skrá sem ég vil opna.
Nú hvað á ég að gera?
Mig langar að lesa úr þessari skrá. Hvernig les ég úr skrá?
[Nemandi] Þú opnar það fyrst. >> Já.
Svo fopen. Hvað er fopen líta út?
[Nemandi] filename. >> [Bowden] Filename er að fara að vera argv [1].
[Nemandi] Og svo það sem þú vilt gera við það, svo - >> [Bowden] Já.
Svo ef þú hefur ekki muna, getur þú bara gert mann fopen,
þar sem það er að fara að vera const char * slóð þar sem leið er filename,
const char * ham.
Ef þú skyldir ekki muna hvaða háttur er, þá er hægt að leita að ham.
Inni síður maður, rista karakter er það sem þú getur notað til að leita að hlutum.
Svo ég tegund / ham til að leita að háttur.
N og N er það sem þú getur notað til að hjóla í gegnum the leita leiki.
Hér segir hann þann ham rök benda til streng
byrja með einn af eftirfarandi röð.
Svo r, Skoða texta skrá til að lesa. Það er það sem við viljum gera.
Til að lesa, og ég vil geyma það.
Málið er að fara að vera skrá *. Nú hvað vil ég gera?
Gefðu mér sekúndu.
Allt í lagi. Nú hvað vil ég gera?
[Nemandi] Athugaðu hvort það er NULL. >> [Bowden] Já.
Í hvert sinn sem þú opnar skrá, ganga úr skugga um að þú ert vel fær um að opna hana.
>> Nú vil ég gera það termios efni þar sem ég vil fyrst að lesa núverandi mínar stillingar
og vista þau í eitthvað, þá vil ég að breyta stillingum mínum
að henda hvaða staf sem ég pikka,
og þá vil ég að uppfæra þessar stillingar.
Og svo í lok áætlunarinnar, vil ég að breyta aftur yfir í upphaflegar stillingar minn.
Svo strúktúr er að fara að vera termios tegund, og ég ætla að fara að vilja tvö af þeim.
Sú fyrsta er að fara að vera current_settings mín,
og hann ætlar að vera hacker_settings mín.
Fyrst ætla ég að fara til að vilja vista mínar stillingar,
þá er ég að fara til að vilja endurnýja hacker_settings,
og þá leið í lok áætlun mína, vil ég snúa við núverandi stillingar.
Svo vista núverandi stillingar, leið sem virkar, við maður termios.
Við sjáum að við höfum þetta int tcsetattr, int tcgetattr.
Ég fara í termios strúktúr með músina sína.
Leiðin þetta mun líta út - I've þegar gleymt hvað fall var kallað.
Afrita og líma það.
Svo tcgetattr, þá vil ég fara í strúktúr sem ég er að vista upplýsingar í,
sem er að fara að vera current_settings,
og fyrsta rifrildi er skrá lýsing á sem ég vil vista eiginleika.
Hvaða skrá lýsing er er eins og hvenær þú opnar skrá, fær það skrá lýsing.
Þegar ég fopen argv [1], fær það skrá lýsing sem þú ert að vísa
þegar þú vilt lesa eða skrifa á það.
Það er ekki skrá lýsing sem ég vil nota hérna.
Það eru þrír skrá descriptors þú hefur sjálfgefið,
sem eru staðlaðar í, staðall út og staðalskekkja.
Sjálfgefið, held ég að það er staðall í er 0, staðall út er 1, og staðall villa er 2.
Svo hvað vil ég að breyta stillingum?
Mig langar að breyta stillingum þegar ég lenti á staf,
Ég vil það að kasta að staf í burtu í stað þess að prenta það á skjáinn.
Hvað Stream - staðalbúnaður í, venjulegu út, eða staðalskekkja -
bregst við það þegar ég slegið á lyklaborðinu? >> [Nemandi] Standard inn >> Já.
Þannig að ég get annaðhvort ekki 0 eða ég get gert stdin.
Ég er að fá current_settings af venjulegu inn
>> Nú vil ég að uppfæra þessar stillingar,
svo fyrst ég afrita inn hacker_settings hvað current_settings mínir eru.
Og hvernig structs vinna er það bara að afrita.
Þetta afrit öllum sviðum, eins og þú vildi búast við.
>> Nú vil ég að uppfæra sumum sviðum.
Þegar litið er á termios, myndir þú þurfa að lesa í gegnum mikið af þessu
bara til að sjá hvað þú vilt að leita að,
en fánar sem þú ert að fara að vilja til að leita að er echo,
svo ECHO Echo inntak stafir.
Fyrst vil ég að setja - I've þegar gleymt hvað svæðin eru.
Þetta er það sem strúktúr lítur út.
Svo stillingar inntak ég held að við viljum breyta.
Við munum líta á lausn til að ganga úr skugga um það er það sem við viljum breyta.
Við viljum breyta lflag í því skyni að koma í veg fyrir að þurfa að leita í gegnum þetta allt.
Við viljum breyta staðbundnum stillingar.
Þú þyrftir að lesa í gegnum þetta allt hlutur til að skilja þar sem allt tilheyrir
sem við viljum breyta.
En það er inni í staðbundnum stillingar þar sem við erum að fara til að vilja breyta því.
Svo er hacker_settings.cc_lmode hvað það er kallað.
c_lflag.
Þetta er þar sem við komum inn í Bita rekstraraðila.
Við erum eins konar út af tími, en við munum fara í gegnum það raunverulegur fljótur.
Þetta er þar sem við komum inn í Bita rekstraraðila,
þar sem ég held að ég sagði einu sinni fyrir löngu að þegar þú byrjar að takast á við fánar,
þú ert að fara að vera með Bita rekstraraðili mikið.
Hver hluti í fána samsvarar einhvers konar hegðun.
Svo hér, þessi biti er fullt af mismunandi hlutum, þar sem allar þær meina eitthvað annað.
En það sem mig langar til að gera er bara að slökkva á hluti sem svarar til ECHO.
Svo til að snúa það burt ég & = ¬ Echo.
Reyndar held ég að það er eins og techo eða eitthvað. Ég ætla bara að fara að athuga aftur.
Ég get termios það. Það er bara ECHO.
ECHO er að fara að vera einn hluti.
¬ ECHO er að fara að þýða allt bits er stillt á 1, sem þýðir að allir fánar eru sett til að sanna
nema Echo hluti.
Með því að binda enda staðbundin fánar minn með þetta, þá þýðir það allt flöggum sem eru stillt á satt
verður samt að vera stillt á satt.
Ef ECHO merkja mitt er stillt á rétt, þá er þetta víst stillt á rangar á Echo fána.
Svo snýr þetta lína af kóða bara af Echo fána.
Önnur línur af kóða, ég bara afrita þau í þágu tíma og útskýra þær.
Í lausninni, sagði hann 0.
Það er sennilega betra að sérstaklega segja stdin.
>> Takið eftir að ég er líka að gera echo | ICANON hér.
ICANON átt við eitthvað sérstakt, sem þýðir Canonical ham.
Hvað Canonical ham leið er oftast þegar þú ert að slá út the stjórn lína,
staðall á ekki að vinna neitt fyrr en þú högg newline.
Svo þegar þú GetString, þú skrifar fullt af hlutum, þá högg newline.
Það er þegar það er sent til staðall inn
Það er sjálfgefið.
Þegar ég slökkva Canonical ham, nú hvert einasta staf þú ýtir
er það sem fær að vinna, sem er venjulega góður af slæmt vegna þess að það er hægt að vinna þetta,
sem er hvers vegna það er gott að biðminni það í heilu línum.
En ég vil hvern staf til að vinna
þar sem ég vil ekki að bíða fyrir mig að lemja newline
áður en það ferli alla stafina sem ég hef verið að skrifa.
Þetta slekkur Canonical ham.
Þetta efni þýðir bara þegar það ferli raun stafi.
Þetta þýðir að vinna þau strax, um leið og ég er að skrifa þá, vinna þá.
Og þetta er aðgerð sem er að uppfæra stillingar minn fyrir staðall í,
og TCSA þýðir gera það núna.
The annar valkostur er að bíða þar til allt sem er nú á straumi er afgreidd.
Það skiptir í raun ekki máli.
Bara núna breytt stillingum mínum að vera hvað sem er í hacker_typer_settings.
Ég held að ég kallaði hana hacker_settings, þannig að við skulum breyta því.
Breyta öllu til hacker_settings.
>> Nú í lok dagskrá okkar við erum að fara að vilja til að snúa
hvað er nú inni normal_settings,
sem er að fara að bara líta út eins og normal_settings.
Tilkynning Ég hef ekki breytt einhverju normal_settings mínum síðan upphaflega að fá það.
Þá bara að breyta þeim aftur, framhjá ég þær aftur í lokin.
Þetta var uppfærsla. Allt í lagi.
>> Nú inni hér ég ætla bara að útskýra kóðann í þágu tíma.
Það er ekki það mikið kóða.
Við sjáum við að lesa staf frá the skrá. Við kallaði það f.
Nú getur þú maður fgetc, en hvernig fgetc er að fara að vinna
er það bara er að fara að skila staf sem þú lest bara eða EOF,
sem svarar til the endir af the skrá eða einhver villa gerast.
Við erum að lykkja, halda áfram að lesa einn staf af skrá,
fyrr en við höfum keyrt út af stöfum til að lesa.
Og á meðan við erum að gera það, bíða við á einum staf frá staðli tommu
Hvert einasta skipti sem þú skrifar eitthvað á the stjórn lína,
sem er að lesa í karakter frá staðli inn
Þá putchar er bara að fara að setja á bleikju við að lesa hér upp úr skrá til staðlaða út.
Þú getur maður putchar, en það er bara að setja í staðal út, það er að prenta þessi karakter.
Þú getur líka bara gert printf ("% c", c), sömu hugmynd.
Það er að fara að gera megnið af starfi okkar.
>> Það síðasta sem við erum að fara til að vilja gera er bara fclose skrá okkar.
Ef þú fclose ekki, það er minni leka.
Við viljum fclose skrána opnuðum upphaflega, og ég held að það er það.
Ef við gerum það, fékk ég þegar vandamál.
Við skulum sjá.
Hvað gerði það að kvarta?
Bjóst við 'int' en rifrildi er af gerðinni "struct _IO_FILE * '.
Við munum sjá hvort það virkar.
Aðeins leyft í C99. Augh. Allt í lagi, gera hacker_typer.
Nú erum við að fá fleiri gagnlegar lýsingar.
Svo nota undeclared auðkenni 'normal_settings'.
Ég vissi ekki að kalla það normal_settings. Ég kallaði það current_settings.
Svo skulum breyta allt um það.
Nú liggur rifrildi.
Ég ætla að gera þetta 0 fyrir nú.
Allt í lagi. . / Hacker_typer cp.c.
ÉG einnig did ekki að hreinsa skjáinn í upphafi.
En þú getur litið til baka í síðasta vandamál sett til að sjá hvernig þú hreinsa skjáinn.
Það er bara prentun tákn
á meðan þetta er að gera það sem ég vil gera.
Allt í lagi.
Og hugsa um hvers vegna þetta þarf að vera 0 í stað stdin,
sem ætti að vera # skilgreina 0,
þetta er að kvarta yfir að -
Áður en þegar ég sagði að það er skrá descriptors en þá verður þú einnig skrá * þínu,
skrá lýsing er bara eina heiltölu,
en skrá * hefur a heild búnt af efni í tengslum við það.
Ástæðan að við þurfum að segja 0 stað stdin
er að stdin er skrá * sem bendir til að hlutur sem er tilvísun skrá lýsing 0.
Svo jafnvel upp hér þegar ég fopen (argv [1], ég er að fá skrá * til baka.
En einhvers staðar í þeirri skrá * er hlutur sem samsvarar skrá lýsing fyrir þessi skrá.
Ef þú líta á the man síðunnar fyrir opinn, þannig að ég held að þú þarft að gera maður 3 Opnaðu - Nei -
maður 2 opin - já.
Ef þú horfir á síðuna til að opna, opna er eins og minni-stigi fopen,
og það er aftur raunverulegt skrá lýsing.
fopen er fullt af efni á toppur af opinn,
sem í stað þess að koma aftur bara að skrá lýsing skilar A heild skrá * músina
inni sem er lítil skrá lýsing okkar.
Svo staðall í átt við * FILE hlutur,
en 0 vísar til bara lýsing skrá staðall í sjálfu sér.
>> Spurningar?
[Hlær] blés í gegnum það.
Allt í lagi. Við erum að gera. [Hlær]
>> [CS50.TV]