[Powered by Google Translate] [Valgrind]
[Nate Hardison, Harvard University]
To je CS50, CS50.TV]
Niektoré z najťažších chýb v programoch C
pochádzajú z nezvládnutie pamäte.
Existuje obrovské množstvo spôsobov, ako skrutka veci do poriadku,
vrátane rozdelenia nesprávne množstvo pamäte,
zabudol inicializovať premenné,
písanie pred alebo po skončení pufri,
a uvoľnenie udržať pamäť viackrát.
Tieto príznaky sa pohybujú od prerušovaných pády
k záhadne prepísaných hodnôt,
často v miestach a časoch ďaleko vzdialených od pôvodného chyby.
Trasovanie sledované problematiky späť na základnú príčinu
môže byť náročné,
ale našťastie je tu užitočné program nazvaný Valgrind
ktoré môže urobiť veľa pomôcť.
>> Spustenie programu pod Valgrind k tomu, aby
Rozsiahla kontrola pridelenie haldy pamäte a prístupy.
Pri Valgrind zistí problém, to vám dáva bezprostredné,
priame informácie, ktoré vám umožnia
ľahšie nájsť a opraviť problém.
Valgrind tiež správy o menej smrtiaca problémy s pamäťou,
ako úniky pamäte, prideľovanie pamäte haldy,
a zabudol uvoľniť ju.
Rovnako ako náš prekladač, klap, v našom debuggeru GDB,
Valgrind je slobodný softvér, a je inštalovaný na zariadení.
Valgrind beží na binárny spustiteľný súbor,
nie je vaša. c alebo. h súbory zdrojových kódov,
takže sa uistite, ste kompiloval up-to-date kópiu vášho programu
pomocou rinčať alebo Make.
Potom môže spustením programu podľa Valgrind byť
tak jednoduché, ako len skratky štandardné programu príkaz so slovom Valgrind,
ktorý sa spustí Valgrind a spustí program, vo vnútri nej.
Pri spustení, Valgrind sa niektoré zložité
jiggering nastaviť spustiteľný pre pamäťové kontroly,
tak to môže trvať trochu sa dostať hore a beží.
Program potom bude vykonávať normálne, či už je to oveľa pomalšie,
a keď to skončí, bude Valgrind vytlačiť súhrn jeho využitie pamäte.
Ak všetko pôjde dobre, bude to vyzerať nejako takto:
V tomto prípade,. / Clean_program
je cesta k programu chcem spustiť.
A aj keď to človek nemá žiadne argumenty,
ak sa to som práve pripináčika je na konci tohto príkazu ako zvyčajne.
Clean program je len hlúpa program, ktorý som vytvoril
, Ktorá rozdeľuje priestor pre blok ints na halde,
dať nejaké hodnoty v rámci nich, a uvoľní celý blok.
To je to, čo natáčate pre, bez chýb a bez úniku.
>> Ďalším dôležitým metrika je celkový počet pridelených bytov.
V závislosti na programe, ak vaše pridelenie sú v MB alebo vyššia,
ste pravdepodobne robíte niečo zle.
Ste zbytočne ukladanie duplicitné?
Používate haldy pre skladovanie, kedy by bolo lepšie použiť zásobník?
Takže, chyby pamäte je naozaj zlý.
Čím viac zjavné tie spôsobujú veľkolepé zrútenia,
ale aj potom to môže ešte byť ťažké určiť
čo presne viedlo k havárii.
Viac zákerne, program s pamäťou chybou
môže ešte zostaviť čisto
a môže stále zdá pracovať správne
pretože sa podarilo získať šťastie väčšinu času.
Po niekoľkých "úspešných výsledkov,"
môžete len myslieť, že zrážka je náhoda v počítači,
ale počítač sa nikdy nemýli.
>> Beh Valgrind vám môže pomôcť vystopovať príčinu viditeľných chýb pamäte
rovnako ako nájsť číha chyby, ktoré nie sú ešte ani vedieť.
Zakaždým, keď Valgrind zistí problém, vytlačí informácie o tom, čo to pozorované.
Každá položka je pomerne stručná -
zdroj línie protiprávneho pokynu, čo je problém,
a trochu info o zapojených pamäti -
ale často je to dosť informácií, aby nasmerovať pozornosť na správnom mieste.
Tu je príklad Valgrind beží na kočíku programu
, Ktorý robí neplatný čítanie haldy pamäte.
Vidíme žiadne chyby alebo varovania v kompilácii.
Uh-oh, chyba zhrnutie hovorí, že tam sú dve chyby -
dva neplatné číta veľkosti 4 - bytov, že je.
Obaja zlé číta došlo v hlavnej funkcie invalid_read.c,
prvý na riadku 16 a druhý na riadku 19.
Poďme sa pozrieť na kód.
Vyzerá to, že prvé volanie printf snaží prečítať jednu int za koncom nášho bloku pamäte.
Ak sa pozrieme späť na výstupe Valgrind je,
vidíme, že Valgrind nám povedal presne to.
Sídlo snažíme čítať začne 0 bajtov
za koncom bloku o veľkosti 16 bajtov -
štyri 32-bitové ints že pridelené.
To znamená, že adresa sa snažíme čítať začína hneď na konci nášho bloku,
rovnako ako vidíme v našom zlom printf hovoru.
Teraz by neplatná čitateľov zdať, že veľký problém,
ale ak používate tieto dáta na riadenie toku programu -
Napríklad ako súčasť if alebo loop -
potom sa veci môžu ticho pokazí.
Pozrite sa, ako môžem spustiť invalid_read programu
a nič neobvyklé deje.
Scary, čo?
>> Teraz sa poďme pozrieť na niektoré ďalšie druhy chýb, ktoré sa môžu vyskytnúť v kóde,
a uvidíme, ako Valgrind detekuje.
Práve sme videli príklad s invalid_read,
takže teraz poďme pozrieť o invalid_write.
Opäť platí, že žiadne chyby alebo varovania v kompilácii.
Dobre, Valgrind hovorí, že tam sú dve chyby v tomto programe -
a invalid_write a invalid_read.
Poďme sa pozrieť na tento kód.
Vyzerá to, že máme inštanciu klasické strlen plus jeden bug.
Kód nie je malloc navyše bajt priestoru
pre / 0 charakteru,
takže keď str kópie išla písať to na ssubstrlen "cs50 skaly!"
to napísal 1 byte za koncom nášho bloku.
The invalid_read prichádza, keď urobíme našu výzvu printf.
Printf skončí čítanie neplatné pamäte pri čítaní / 0 znak
ako to vyzerá na konci tohto E reťazec je tlač.
Ale nič z toho unikol Valgrind.
Je vidieť, že to zachytil invalid_write ako súčasť str kópie
na riadku 11 hlavné, a invalid_read je súčasťou printf.
Rock on, Valgrind.
Opäť, mohlo by to vyzerať ako veľký problém.
Môžeme spustiť tento program znovu a znovu mimo Valgrind
a nie je vidieť žiadne chybové príznaky.
>> Avšak, poďme sa pozrieť na nepatrnú variácií tohto vidieť
ako sa veci môžu naozaj zlé.
Takže, udelené, sme zneužívajú veci viac ako len trochu v tomto kóde.
Sme len prideľovanie priestor na halde pre dva reťazce
dĺžka cs50 hornín,
Tentoraz, keď si spomenul / 0 znak.
Ale potom sme sa hodiť v super-dlhé reťazce do pamäťového bloku
že S je ukazuje.
Aký vplyv bude to mať na pamäti, že blok T odkazuje na?
No, ak T poukazuje na pamäti, že to jednoducho vedľa S,
prichádza tesne po nej,
potom by sme mohli prepísať časť T.
Poďme spustením tohto kódu.
Pozrite sa na to, čo sa stalo.
Reťazce sme uložené v našich haldy blokoch oboch zrejme tlačené správne.
Nič sa zdá v poriadku vôbec.
Avšak, vráťme sa do nášho kódu a
komentár mimo riadok, kde sme kopírovať cs50 skaly
do druhého bloku pamäte, ktorý by ukazoval t
Teraz, keď sme sa spustiť tento kód, ktorý sme mali
zobraziť iba obsah prvého bloku pamäte vytlačiť.
Whoa, aj keď sme nemali str kópie
všetky znaky do druhého bloku haldy, ten, na ktorý ukazuje T,
dostaneme vytlačte.
Naozaj, string sme napchal do nášho prvého bloku
obsadil prvé blok a do druhého bloku,
Vďaka všetko zdá normálne.
Valgrind, keď nám hovorí skutočný príbeh.
Tam ideme.
Všetky tie neplatné číta a zapisuje.
>> Poďme sa pozrieť na príklad iného druhu chyby.
Tu urobíme niečo trochu nešťastným.
Sme chytiť priestor pre int na halde,
a my inicializácii int ukazovateľ - p - prejdite na tomto priestore.
Avšak, zatiaľ čo naša ukazovateľ je inicializovaný,
údaje, ktoré to poukazujú len sa čo nevyžiadanej je v tejto časti haldy.
Takže keď sme sa načítať tieto dáta do int i,
sme technicky inicializovať aj,
ale my to s nevyžiadanou dát.
Výzva presadiť, čo je šikovný ladenie makrá
definované v výstižne pomenované uplatniť knižnice,
preruší program, ak jeho skúšobnú stav zlyhá.
To znamená, že ak je aj nie je 0.
V závislosti na tom, čo bolo v haldy priestoru, ktorý by ukazoval p,
tento program môže fungovať niekedy aj zlyhanie inokedy.
Ak to funguje, sme len dostať šťastie.
Kompilátor nebude chytiť túto chybu, ale Valgrind istí, že.
Tu vidíme chybu vyplývajúce z našej použitia tohto nevyžiadanej údajov.
>> Keď prideliť haldy pamäte, ale to nie je navrátiť, alebo uvoľniť ho,
, Ktorá sa nazýva únik.
Pre malé, krátkotrvajúci program, ktorý beží a okamžite východy,
úniky sú pomerne neškodné,
ale pre projekt väčšej veľkosti a / alebo dlhovekosť,
aj malá netesnosť môže zhoršiť do niečoho hlavnej.
Pre CS50, my očakávame, že
postarať o uvoľnenie všetkých haldy pamäte, ktoré prideliť,
pretože chceme, aby ste vybudovať zručnosti správne zvládnuť ručné proces
vyžaduje C.
Ak chcete tak urobiť, musí váš program mať presné
one-to-one korešpondencie medzi malloc a bezplatná volanie.
Našťastie, môže Valgrind pomôže s úniky pamäte taky.
Tu je deravý program s názvom leak.c, že ​​prideľuje
priestor na halde, píše, ale nie je to uvoľniť.
Sme ho skompilovať s Make a spustite ho pod Valgrind,
a vidíme, že, zatiaľ čo my máme žiadne chyby pamäti,
máme jednu dieru.
K dispozícii je 16 bytov definitívne stratil,
čo znamená, že ukazovateľ tejto pamäte nie je v rozsahu, keď program skončil.
Teraz, Valgrind nedáva tony informácií o úniku,
ale ak sa budeme riadiť týmto malú poznámku, že to dáva dole smerom k spodnej časti svojej správy
znovu spustiť s - leak-check = full
Pre zobrazenie detailných informácií o unikli pamäti,
dostaneme ďalšie informácie.
Teraz, v haldy zhrnutie,
Valgrind nám hovorí, kde sa pamäť, ktorá bola stratená pôvodne pridelené.
Rovnako ako poznáme z pohľadu v zdrojovom kóde,
Valgrind nás informuje, že sme unikli pamäte
pridelené s výzvou na malloc na linke 8 leak.c
v hlavnej funkcii.
Docela šikovný.
>> Valgrind kategorizuje úniky pomocou tieto pojmy:
Definitívne stratil - to je halda pridelené pamäte
na ktoré je program už má ukazovateľ.
Valgrind vie, že si kedysi mal ukazovateľ, ale od tej doby stratil prehľad o tom.
Táto pamäť je určite unikli.
Nepriamo stratil - to je halda pridelené pamäte
, Na ktoré sa len ukazovatele na nej sú tiež stratené.
Napríklad, ak ste stratili svoj ukazovateľ na prvý uzol prepojeného zoznamu,
potom prvý uzol samo o sebe by byť definitívne stratil,
zatiaľ čo akékoľvek následné uzly by sa nepriamo stratená.
Možno stratil - to je halda pridelené pamäte
na ktoré Valgrind nemôže byť istý, či je ukazovateľ, alebo nie.
Stále dosiahnuteľný je haldy pridelené pamäte
na ktoré je program ešte má ukazovateľ na výstupe,
čo zvyčajne znamená, že globálna premenná na neho ukazuje.
Ak chcete skontrolovať tieto úniky, budete musieť zadať aj možnosť
- Stále dosiahnuteľné = yes
v vyvolanie Valgrind.
>> Tieto rôzne prípady môžu vyžadovať rôzne stratégie pre ich čistenie up,
ale úniky by mali byť odstránené.
Bohužiaľ, ktorým sa ustanovujú úniky byť ťažké urobiť,
pretože nesprávne volanie zadarmo môže vyhodiť svoj program.
Napríklad, keď sa pozrieme na invalid_free.c,
vidíme príklad zlého pamäte deallocation.
Čo by malo byť jedno volanie uvoľniť celý blok
pamäte, na ktorý ukazuje int_block,
namiesto toho sa snaží oslobodiť každý int veľkosti sekcii
z pamäte individuálne.
To sa nepodarí katastrofálne.
Boom! Čo chybe.
To rozhodne nie je dobré.
Ak neviete ako ďalej s týmto druhom chyby, aj keď, a neviete, kam sa pozerať,
oprieť o svojho nového najlepšieho priateľa.
Uhádli ste - Valgrind.
Valgrind, ako vždy, presne vie, čo sa deje.
V Alloc a voľný počty nezodpovedajú.
Máme 1 Alloc a 4 oslobodzuje.
A Valgrind nám tiež hovorí, kde sa prvý zlé volanie zadarmo -
ten, ktorý spustil explóziu - prichádza z -
linka 16.
Ako vidíte, zlé volanie zadarmo sú naozaj zlé,
takže odporúčame nechať vášho programu únik
, Zatiaľ čo vy pracujete na získanie funkcie správne.
Začať hľadať únik až po váš program pracuje správne,
bez ďalších chýb.
>> A to je všetko, čo sme dostali za toto video.
Tak čo ešte čakáte?
Prejsť beží Valgrind na vašich programov práve teraz.
Moje meno je Nate Hardison. To je CS50. [CS50.TV]