[Powered by Google Translate] [Valgrind]
[Nate Hardison, Harvard University]
Þetta er CS50, CS50.TV]
Sumir af erfiðustu galla í C forrit
koma frá óstjórn minni.
There ert a gríðarstór tala af lifnaðarhættir til að skrúfa það upp,
þ.mt úthlutun rangt magn af minni,
gleyma að frumstilla breytur,
skrifa fyrir eða eftir lok biðminni,
og frjáls halda minni mörgum sinnum.
Einkennin eru allt frá hléum hrun
á dularfullur plága gildi,
oft á stöðum og tíma fjarri upprunalegu villu.
Rekja Mæld vandamál aftur til undirliggjandi undirrót
getur verið erfitt,
en sem betur fer að það er gagnlegt forrit sem heitir Valgrind
að geta gert mikið til að hjálpa.
>> Þú keyra forrit undir Valgrind til að gera
víðtæka Eftirlit með Hrúga minni úthlutun og aðgangur.
Þegar Valgrind uppgötva vandamál, gefur það þér strax,
beinar upplýsingar sem gerir þér kleift að
auðveldara að finna og laga vandamálið.
Valgrind einnig skýrslur um hættuminni minni mál,
svo sem leka minni, úthlutun hrúga minni,
og gleyma að losa það.
Eins þýðanda okkar, Clang, í aflúsara okkar, gdb,
Valgrind er frjáls hugbúnaður, og það er sett upp á tækinu.
Valgrind keyrir á executable tvöfaldur þinn,
ekki þín. C eða. klst kóðann skrár,
svo vertu viss um að þú hefur tekið saman upp-til-dagsetning afrit af forritinu
nota Clang eða gera.
Þá, hlaupandi program undir Valgrind má
eins einfalt og bara að prefixing staðall program stjórn með orðinu Valgrind,
sem hefst upp Valgrind og keyrir forritið inni í henni.
Þegar byrjað, Valgrind gerir sum flókin
jiggering að stilla executable fyrir minni stöðva,
svo það getur tekið smá til að fá upp og keyra.
Forritið mun þá framkvæma venjulega, að það mun hægar,
og þegar henni er lokið Valgrind mun prenta yfirlit yfir notkun minni.
Ef allt gengur vel, það mun líta eitthvað eins og this:
Í þessu tilviki. / Clean_program
er leiðin til áætlunarinnar sem ég vil að hlaupa.
Og á meðan þetta er ekki að taka neinar rök,
Ef það gerði ég myndi bara tittur þá á að enda á stjórn eins og venjulega.
Clean program er bara kjánalegt lítið forrit sem ég skapa
sem úthlutar pláss fyrir blokk ints á hrúga,
setja nokkrar gildi innan þeirra, og frjáls alla blokk.
Þetta er það sem þú ert að skjóta fyrir, engar villur og enginn leki.
>> Annar mikilvægur mælikvarði er fjöldi bytes úthlutað.
Það fer eftir áætlun, ef úthlutun þín eru á megabæti eða hærra,
þú ert líklega að gera eitthvað rangt.
Ert þú að geyma óþörfu afrit?
Ert þú using the hrúga til geymslu, þegar það væri betra að nota stafla?
Svo minni villur má sannarlega illt.
Því fleiri overt sjálfur valda stórkostlegt hrun,
en jafnvel þá getur það samt verið erfitt að ákvarða
hvað leiddi nákvæmlega til hrun.
Meira insidiously, forrit með minni villa
getur samt saman eðlilega
og enn er hægt að virðast til að virka rétt
vegna þess að þú tókst að fá heppinn mest af tímanum.
Eftir nokkra "vel niðurstöðum,"
þú gætir bara held að hrun er fluke á tölvunni,
en tölvan er aldrei rangt.
>> Running Valgrind getur hjálpað þér að elta uppi orsök sýnilegar villur minni
og finna lurking villur sem þú þarft ekki einu sinni enn að vita um.
Í hvert skipti Valgrind uppgötva vandamál, prentar það upplýsingar um það fram.
Hvert atriði er nokkuð terse -
uppspretta lína í beinum kennslu, hvað málið er,
og smá upplýsingar um minni þátt -
en oft er það nóg upplýsingar til að beina athygli þína á réttum stað.
Hér er dæmi um Valgrind keyra á buggy program
sem er ógilt las um minni hrúga.
Við sjáum engar villur eða viðvaranir á samantekt.
Uh-ó, villa samantekt segir að það eru tvær villur -
tvö ógild lesin í stærð 4 - bytes, sem er.
Bæði slæmt les orðið á helstu virkni invalid_read.c,
fyrst á línu 16 og seinni á línu 19.
Við skulum líta á kóðann.
Lítur út eins og fyrsta símtalinu til printf reynir að lesa eina int framhjá lok blokk minni okkar.
Ef við lítum til baka á framleiðslu Valgrind er,
sjáum við að Valgrind sagði okkur einmitt það.
Heimilisfangið sem við erum að reyna að lesa byrjar 0 bytes
framhjá lok blokk stærð 16 bæt -
fjórir 32-bita ints sem við úthlutað.
Það er, heimilisfang við vorum að reyna að lesa byrjar rétt í lok blokk okkar,
eins og við sjáum í slæmum printf símtali okkar.
Nú, ógilt lesin gæti ekki virðast eins og það stór af a samningur,
en ef þú ert að nota þessi gögn til að stjórna flæði program -
til dæmis, eins og hluti af óákveðinn greinir í ensku ef yfirlýsingu eða lykkja -
þá hluti geta hljóður fara illa.
Horfa hvernig ég get keyrt invalid_read program
og ekkert út af the venjulegur gerist.
Scary, ha?
>> Nú, við skulum líta á nokkrar fleiri tegundir af villum sem þú gætir fundur í kóðanum þínum,
og við munum sjá hvernig Valgrind uppgötva þá.
Við sáum bara dæmi um invalid_read,
Svo nú skulum kíkja á invalid_write.
Aftur, engar villur eða viðvaranir á samantekt.
Jæja, Valgrind segir að það eru tvær villur í þessari áætlun -
og invalid_write og invalid_read.
Við skulum kíkja á þennan kóða.
Útlit eins og við höfum fengið eintak af klassískum strlen plús einn galla.
Kóðinn virkar ekki malloc auka bæti af plássi
í / 0 staf,
svo þegar Str afrit fór að skrifa það á ssubstrlen "cs50 rocks!"
það skrifaði 1 bæti framhjá lok blokkinni okkar.
The invalid_read kemur þegar við að hringja okkar til printf.
Printf endar lestur ógilda minni þegar það les / 0 karakter
eins og það lítur út í lok þessa E streng það er prentun.
En ekkert af þessu slapp Valgrind.
Við sjáum að það náði invalid_write sem hluta af STR afrita
á línu 11 af helstu og invalid_read er hluti af printf.
Rock á, Valgrind.
Aftur, þetta gæti ekki virðast eins og a stór samningur.
Við getum keyrt þetta forrit aftur og aftur utan Valgrind
og ekki séð einhverjar villur einkenni.
>> En við skulum líta á smá breytingu á þessu til að sjá
hvernig það getur fengið mjög slæmt.
Svo, veitt, við erum að misnota það meira en bara smá í þennan kóða.
Við erum aðeins að úthluta pláss á hrúga fyrir tvo strengi
lengd cs50 steina,
í þetta sinn, að muna / 0 staf.
En þá erum við að kasta í a frábær-langa streng í minni blokk
sem S er að benda á.
Hvaða áhrif mun það hafa á minni blokk sem T bendir á?
Jæja, ef T bendir á minni sem er bara við hliðina á S,
koma bara eftir það,
þá við gætum hafa skrifað yfir hluta af T.
Við skulum hlaupa þennan kóða.
Horfðu á það sem gerðist.
Strengi við geymd í blokkum hrúga okkar bæði virtust hafa prentað út á réttan hátt.
Ekkert virðist rangt yfirleitt.
En við skulum fara aftur í númerið okkar og
athugasemd út línunni þar sem við afrita cs50 steina
í seinni minni blokk, benti á eftir t.
Nú, þegar við hlaupum þennan kóða við ættum
aðeins sjá innihald fyrstu minni blokk prenta út.
Vá, jafnvel þó að við gerðum ekki STR afrit
allir stafir í seinni hrúga blokk, einn benti á eftir T,
við fáum prenta út.
Reyndar, the band við fyllt í fyrsta blokk okkar
overran fyrsta blokk og í annarri blokk,
að allt virðist eðlilegt.
Valgrind, þó segir okkur sanna sögu.
Svona.
Allt sem ógild les og skrifar.
>> Við skulum líta á dæmi um annars konar villa.
Hér gerum við eitthvað frekar óheppileg.
Við grípa pláss fyrir INT á hrúga,
og við frumstilla int músina - p - til að benda á þessi rými.
Hins vegar, á meðan bendillinn okkar er frumstilla,
gögn að það er vísa til bara hefur hvað skran er í þeim hluta hrúga.
Svo þegar við hlaða þessi gögn inn í int i,
við frumstilla tæknilega i,
en við gerum það með gagna skran.
Símtalið til að halda, sem er handlaginn kembiforrit þjóðhagsleg
skilgreint í viðeigandi nafni halda bókasafn,
verður hætt við áætlun ef próf ástand hennar ekki.
Það er, ef ég er ekki 0.
Það fer eftir því hvað var í hrúga rúm, benti á eftir p,
Þetta forrit gæti virkað stundum og ekki á öðrum tímum.
Ef það virkar, við erum bara að fá heppinn.
The þýðanda mun ekki grípa þessa villu, en Valgrind viss um að vilja.
Þar sjáum við villa stafar af notkun okkar á að skran gögn.
>> Þegar þú skiptir hrúga minni en deallocate ekki eða losa það,
sem er kallað leka.
Fyrir litla, skamman tíma forrit sem keyrir og strax hættir,
leka eru nokkuð skaðlaus,
en verkefni af stærri stærð og / eða langlífi,
jafnvel a lítill leki getur blanda í eitthvað meiriháttar.
Fyrir CS50, við ætlast til að þú
annast frjáls allt hrúga minni sem þú skiptir,
þar sem við viljum að þú að byggja upp færni til almennilega takast á handbók aðferð
krafist C.
Til að gera það, program ætti að vera nákvæm
einn-á-mann samskipti milli malloc og ókeypis símtöl.
Sem betur fer, Valgrind getur hjálpað þér með leka minni líka.
Hér er a leaky forrit sem heitir leak.c sem úthlutar
pláss á hrúga, skrifar við það, en ekki losa það.
Við þýða það með að gera og hlaupa undir Valgrind,
og við sjáum að, en við höfum ekkert minni villur,
við höfum einn leka.
Það eru 16 bæti örugglega glatað,
sem þýðir að bendillinn til að minni var ekki að umfangi þegar forritið lauk.
Nú, Valgrind ekki gefa okkur a tonn af upplýsingum um leka,
en ef við fylgjum þessum litla texta sem það gefur niður að botni skýrslu
að endursýning með - leka-stöðva = fullur
til að sjá allar upplýsingar um leki minni,
við munum fá meiri upplýsingar.
Nú, í hrúga samantekt,
Valgrind segir okkur hvar minni sem var glataður var upphaflega úthlutað.
Rétt eins og við þekkjum frá útlit á the uppspretta merkjamál,
Valgrind upplýsir okkur að við leki minni
úthlutað með símtali til malloc á línu 8 í leak.c
í helstu hlutverk.
Pretty nifty.
>> Valgrind afdráttarlaus leka með þessum skilmálum:
Ákveðið glatað - þetta er hrúga úthlutað minni
sem forritið er ekki lengur með músina.
Valgrind veit að þú hefðir einu sinni á músina en hefur síðan misst utan um það.
Þetta minni er örugglega leki.
Óbeint tapað - það er hrúga úthlutað minni
sem aðeins ábendingar til það líka hafa tapast.
Til dæmis, ef þú misst músina til fyrsta hnút í tengda listanum,
þá fyrst hnút sjálft myndi örugglega glatað,
en síðari hnútar væri óbeint tapað.
Hugsanlega tapað - það er hrúga úthlutað minni
sem Valgrind getur ekki verið viss um hvort það er bendillinn eða ekki.
Enn er náðist hrúga úthlutað minni
sem forritið enn bendi á brottför,
sem þýðir yfirleitt að alþjóðlegt breytu benda til þess.
Til að athuga þessar leka, munt þú einnig verða að fela í sér möguleika á
- Enn-náðist = já
í ákall þinn Valgrind.
>> Þessar mismunandi tilvikum gæti þurft mismunandi aðferðir til að þrífa þá upp,
en leka ætti að útrýma.
Því miður, ákveða leka getur verið erfitt að gera,
þar rangt símtöl frjáls geta blásið upp program.
Til dæmis, ef við skoðum invalid_free.c,
sjáum við dæmi um slæma minni deallocation.
Hvað ætti að vera eitt símtal að losa alla blokk
minni benti á með int_block,
hefur í staðinn orðið að reyna að losa hvert int-stór kafla
af minni fyrir sig.
Þetta mun mistakast catastrophically.
Boom! Hvaða villa.
Þetta er örugglega ekki gott.
Ef þú ert fastur með þessa tegund af villa, þó, og þú veist ekki hvar á að leita,
falla aftur á nýju bestu vinkonu þinni.
Þú giska á það - Valgrind.
Valgrind, eins og alltaf, veit nákvæmlega hvað er að.
The alloc og frjáls telja passa ekki upp.
Við höfum fengið 1 alloc og 4 frjáls.
Og Valgrind segir okkur einnig þar sem fyrsta slæmt frjáls kalla -
sá sem setti blowup - kemur frá -
lína 16.
Eins og þú sérð, eru slæm símtöl til að losa mjög slæmt,
þannig að við mælum með því að láta forrit leka þinn
meðan þú ert að vinna í að fá virkni rétt.
Byrja að leita að leka fyrr en forritið er rétt,
án annarra villur.
>> Og það er allt sem við höfum fengið fyrir þetta myndband.
Nú hvað ert þú að bíða?
Fara keyra Valgrind á forrit núna.
Ég heiti Nate Hardison. Þetta er CS50. [CS50.TV]