[Powered by Google Translate] [Valgrind]
[Nate Hardison, Harvard University]
To je CS50, CS50.TV]
Nekateri izmed najtežjih napak v programih C
izvira iz slabega upravljanja pomnilnika.
Obstaja veliko več načinov, da vijak stvari,
vključno z dodelitvijo napačno količino pomnilnika,
pozablja za inicializacijo spremenljivk,
pisno pred ali po koncu varovalni pas,
in sprostitev ohraniti spomin večkrat.
Simptomi segajo od nestalnih nesreč
na skrivnostno prepišejo vrednosti,
pogosto na krajih in časih daleč od prvotne napake.
Sledenje ugotovljenega problema nazaj na osnovni vzrok koren
lahko izziv,
K sreči pa obstaja program, imenovan v pomoč Valgrind
da lahko naredimo veliko pomagati.
>> Zaženete program, v okviru Valgrind, ki omogočajo
obsežno preverjanje dodelitve kopice pomnilnika in dostopov.
Ko Valgrind zazna težavo, da vam daje takojšnje,
neposredne informacije, ki vam omogoča, da
lažje najti in popraviti težavo.
Valgrind tudi poročila o smrtnih manj vprašanj pomnilniških
kot spomin pušča, dodelitev kup pomnilnika,
in pozablja, da ga osvobodi.
Všeč mi je naš prevajalnik, Jek, v naš iskalnik napak, GDB,
Valgrind je brezplačna programska oprema, in je nameščen na napravi.
Valgrind deluje na vašem binarnem izvršljiv,
ne vaš. ali c. h datoteke izvorne kode,
tako se prepričajte, da ste pripravljeni za up-to-date kopijo programa
z Jek ali narediti.
Potem se lahko izvaja svoj program v okviru Valgrind biti
tako enostavno, kot le prefixing standardni program ukaz z besedo Valgrind,
, ki se zažene Valgrind in zažene program notri.
Ob zagonu, Valgrind ne nekaj kompleks
jiggering nastaviti izvedljivo za pomnilniške preglede,
tako da lahko traja nekaj vstati in teče.
Program bo nato izvršiti normalno, je to veliko bolj počasi,
in ko se konča, bo Valgrind natisniti povzetek svojega pomnilnika.
Če bo šlo vse dobro, bo videti nekako takole:
V tem primeru. / Clean_program
je pot do programa, ki ga želim teči.
In medtem ko ta ne sprejme nobenih argumentov,
če je to storil sem jih samo prečenje na koncu ukaza, kot ponavadi.
Čisto program je samo neumno malo program sem ustvaril
ki namenja prostor za blok ints na kup,
dal nekaj vrednosti znotraj njih, se sprosti celoten blok.
To je tisto, kar ste streljanje, brez napak in ne pušča.
>> Druga pomembna meritev je skupno število dodeljenih bajtov.
Odvisno od programa, če je vaša sredstva so v MB ali višje,
ste verjetno delaš nekaj narobe.
Ali ste po nepotrebnem shranjevanje kopijo?
Ali uporabljate kup za shranjevanje, če bi bilo bolje uporabiti sveženj?
Torej, lahko pomnilnik napak je res zlo.
Bolj očitni tisti povzročijo spektakularne nesreče,
pa še takrat se lahko še vedno težko izslediti
kaj točno je privedlo do nesreče.
Več zahrbtno, program s pomnilniške napake
Še vedno prevesti
in lahko še vedno zdi, da deluje pravilno
ker ti je uspelo priti srečo večino časa.
Po nekaj uspešnih rezultatov ","
Morda vam bodo samo mislim, da je nesreča krompir iz računalnika,
vendar računalnik ni nikoli narobe.
>> Tek Valgrind vam lahko pomaga izslediti vzrok vidnih napak pomnilnika
kot je bil skrit napake sploh ne vemo o tem.
Vsakič Valgrind zazna težavo, jo natisne informacije o tem, kaj opazili.
Vsaka točka je dokaj jedrnato -
vir linija, ki krši navodila, kaj je vprašanje,
in malo informacij o zadevnem spomin -
pogosto pa je dovolj informacij, da ste pozorni na pravo mesto.
Tukaj je primer Valgrind teče na buggy programa
da ne neveljavno branje pomnilnika kopice.
Bomo videli nobenih napak ali opozoril na kompilacijo.
Uh, napaka povzetek pravi, da obstajata dve napake -
2 neveljavna bralcev velikosti 4 - bytes, da je.
Tako slabo bere prišlo v glavno funkcijo invalid_read.c,
Prvi na liniji 16 in 2. na spletu 19.
Oglejmo si kodo.
Izgleda, da je prvi razpis za printf poskuša prebrati 1 int mimo konca našega spomina bloka.
Če se ozremo na izhodu Valgrind je,
vidimo, da Valgrind nam je povedal točno to.
Naslov poskušamo prebrati začne 0 zlogov
po preteku bloka velikosti 16 bajtov -
4 32-bitne ints, da dodeljena.
To pomeni, da je naslov smo poskušali prebrati začne že ob koncu našega bloka,
tako kot smo videli v naši slabi printf klic.
Sedaj veljavna bralcev morda ne zdi, da je velik posel,
če pa boste uporabljali, da so podatki za nadzor pretoka programu -
na primer kot del if stavek ali zanka -
potem se lahko stvari tiho iti slabo.
Oglejte si, kako lahko zaženete program, invalid_read
in nič nenavadnega zgodi.
Grozljivo, kajne?
>> Zdaj pa si oglejmo nekaj več vrst napak, do katerih lahko pride v kodi,
in bomo videli, kako Valgrind jih zazna.
Pravkar smo videli primer za invalid_read,
Tako zdaj pa odjaviti invalid_write.
Še enkrat, brez napake ali opozorila v zbirki.
Ok, Valgrind pravi, da obstajata dve napake v tem programu -
in invalid_write in invalid_read.
Pa poglejmo to kodo.
Izgleda, da imamo primerek klasične strlen plus eno napako.
Kodeks ne malloc dodatno bajt prostora
za / 0 značaja,
tako da, ko str izvod šel na napisati na ssubstrlen "cs50 skale!"
je napisal 1 bajt po preteku našem bloku.
The invalid_read pride, ko naredimo naš poziv k printf.
Printf konča branje neveljavnih spomin, ko bere / 0 značaja
, kot je videti na koncu te E nizu je tiskanje.
Toda nič od tega pobegnil Valgrind.
Vidimo, da je ujel invalid_write v okviru STR kopije
on line 11 Glavni in invalid_read del printf.
Rock on, Valgrind.
Še enkrat, to morda ne zdi nič takega.
Mi lahko zaženete ta program znova in znova zunaj Valgrind
in ne vidim nobenih napak simptomov.
>> Vendar pa si oglejmo rahlo spremembo te videti
kako se lahko stvari zelo slabo.
Torej, se odobri smo zlorablja stvari več kot le košček v tem zakoniku.
Mi smo samo dodelitev prostora na kup za dveh nizov
dolžina cs50 kamnin,
Tokrat se spomnimo / 0 značaja.
Ampak potem vrgel v super-dolg niz v spomin blok
S, ki kaže, da.
Kakšen vpliv bo to imelo na pomnilniški blok, ki kaže na T?
No, če T opozarja pomnilnika, ki je samo v bližini S,
prihaja tik po njej,
potem bi smo zapisali v delu T.
Naj vodijo te kode.
Poglejte, kaj se je zgodilo.
Strune smo shranjeni v naših blokih kopice tako se zdi, da so se natisne pravilno.
Nič se zdi narobe.
Vendar pa pojdimo nazaj v našo kodo in
zakomentirajte črto, kjer smo kopirati cs50 kamenje
v drugi blok pomnilnika, ki ga je opozoril na t.
Zdaj, ko smo teči ta kodeks, naj mi
Samo glej vsebina prvega bloka pomnilnika natisnite.
Vau, čeprav nismo str izvod
vsi znaki v drugem bloku kup, ena je poudaril, da družba T,
smo dobili natisniti.
Dejansko niz smo polni v naši prvi blok
presegla prvi blok in v drugem bloku,
kar vse se zdi normalno.
Valgrind, čeprav nam pove resnično zgodbo.
Takole.
Vsi so neveljavne bere in piše.
>> Oglejmo si primer druge vrste napake.
Tu bomo naredili nekaj precej nesrečno.
Mi zgrabi prostora za notr na kup,
in smo inicializacije int kazalec - p - da kaže na tem prostoru.
Kljub temu, da se inicializira naša kazalec,
podatki, ki jih je, ki kažejo, da je prav, ne glede smeti so v tem delu kup.
Torej, ko smo naložili, da se podatki v int i,
smo tehnično i inicializirati,
vendar smo storili z junk podatkov.
Razpis za uveljavljanje, kar je priročno debugging makro
opredeljeno v aptly imenovan uveljavlja knjižnici
boste prekinili program, če je njen preizkus pogoja ne uspe.
To pomeni, da če jaz ne 0.
Glede na to, kaj je bilo v kup prostora, je povedal, da ga p,
ta program se lahko včasih dela in ne v drugih obdobjih.
Če to deluje, bomo ravno srečen.
Prevajalnik ne bo ujel to napako, vendar je prepričan, da bo Valgrind.
Tam smo videli napako, ki izvira iz naše uporabe, ki junk podatkov.
>> Ko dodelitev kup pomnilnika, vendar ne Drugače pridijeliti ali osvoboditi,
, ki se imenuje pušča.
Za majhno, kratkotrajno programa, ki se zažene in takoj izhode
pušča precej neškodljiva,
ampak za projekt večje velikosti in / ali dolgoživosti,
lahko celo majhna puščanja sestavljena v nekaj velikega.
Za CS50, mi pričakujemo, da boste
poskrbimo za sprostitev vseh kup pomnilnika, ki ga dodeli,
saj želimo graditi znanje za pravilno ravnanje ročni postopek
zahteva C.
Če želite to narediti, mora vaš program ima točno
one-to-one korespondenca med knjižnične funkcije malloc in brezplačne klice.
Na srečo, lahko Valgrind vam pomaga s pomnilniške uhajanja preveč.
Tukaj je utor program, imenovan leak.c, ki dodeljuje
prostora na kup, piše na njej, vendar ga ne osvobodi.
Uspelo nam je zbrati z znamko in ga voziti v Valgrind,
in vidimo, da čeprav nimamo spomin napak,
imamo 1 puščanje.
Obstaja 16 bajtov zagotovo izgubil,
kar pomeni, da je kazalec na ta spomin ni bil v področje, ko se program izstopilo.
Zdaj, Valgrind nam ne daje tone informacij o puščanja,
ampak, če sledimo tej mali, upoštevajte, da se daje dol na dnu svoje poročilo
za ponovno z - puščanja preverite = polna
da bi videli vse podrobnosti ušli spominu,
bomo dobili več informacij.
Zdaj, v kup povzamemo,
Valgrind nam pove kje je spomin, ki je izgubil prvotno dodeljeni.
Tako kot vemo iz pogledate v izvorno kodo,
Valgrind nam sporoča, da smo ušli spomin
dodeljena s pozivom k knjižnične funkcije malloc na spletu 8 leak.c
v glavnem funkcijo.
Precej eleganten.
>> Valgrind razvršča uhajanje z uporabo te pogoje:
Zagotovo izgubili - to je kup dodeljen pomnilnik
je program nima več kazalec.
Valgrind ve, da si nekoč imel kazalec, vendar je od takrat izgubil sled za njim.
Ta spomin je zagotovo ušli.
Posredno izgubili - to je kup dodeljen pomnilnik
katerih edini kazalci na njem so tudi izgubili.
Na primer, če si izgubil kazalec na prvo vozlišče povezan seznam,
potem bi se prvi vozel sama dokončno izgubil,
medtem ko bodo vse nadaljnje vozlišča posredno izgubljena.
Predvidoma izgubili - to je kup dodeljen pomnilnik
ki Valgrind ne morejo biti prepričani, ali je kazalec ali ne.
Še vedno dosegljiva, je kup dodeljen pomnilnik
je program še vedno kazalec na izhod,
kar običajno pomeni, da je globalna spremenljivka kaže na to.
Če želite preveriti te tesnjenje, boste imeli tudi možnost, da se vključi
- Še vedno dosegljiv = da
v vašem sklicevanje na Valgrind.
>> Ti različni primeri lahko zahtevajo različne strategije za njihovo čiščenje,
vendar je treba odpraviti pušča.
Na žalost, lahko določitvi uhajanje težko narediti,
saj lahko nepravilna klici na brezplačno razstrelil svoj program.
Na primer, če pogledamo invalid_free.c,
smo videli primer slabega deallocation pomnilnika.
Kakšen bi moral biti en sam klic sprostiti celoten blok
pomnilnika, ki ga je opozoril na int_block,
je namesto tega postane poskus osvoboditi vsako int velika poglavje
v spomin posebej.
To bo katastrofalno propadel.
Boom! Kakšna napaka.
To zagotovo ni dobro.
Če si zaljubljen s to vrsto napake, čeprav, in ne veste, kje iskati,
pade nazaj na vaš novi najboljši prijatelj.
Uganili ste - Valgrind.
Valgrind, kot vedno, natančno ve, kaj se dogaja.
V alloc in prosti šteje ne ujemajo.
Imamo 1 alloc in 4 osvobaja.
In Valgrind nam tudi pove, kje je prvi prosti slab klic -
1, ki je sprožila Eksplozija - prihaja -
linija 16.
Kot vidite, slabe poziva k brezplačnega so res slabe,
zato vam priporočamo, dajanje v najem vaš programa puščanje
medtem ko delate na pridobivanje funkcionalnost pravilna.
Začni iskanje uhajanja šele potem, ko je vaš program deluje pravilno,
brez kakršnih koli drugih napak.
>> In to je vse, kar imamo za ta video.
Zdaj, kaj še čakaš?
Pojdi teči Valgrind na vaših programih sedaj.
Moje ime je Nate Hardison. To je CS50. [CS50.TV]