[Powered by Google Translate] [Valgrind] [Nate Hardison, Sveučilište Harvard] Ovo je CS50, CS50.TV] Neki od najtežih bugova u C programima dolaze iz lošeg pamćenja. Postoji veliki broj načina da se vijak stvari, uključujući izdvajanja pogrešnu količinu memorije, zaboravljajući da inicijalizirati varijable, pisanje prije ili nakon završetka tampon, i oslobađanje zadržati memorijske više puta. Simptomi se kreću od povremenih ruši da misteriozno prebrisana vrijednosti, često na mjestima iu vremenima daleko od izvornog pogreške. Tragom promatranu problema vratiti na temeljne uzrok može biti izazov, ali srećom tu je pomogla program koji se zove Valgrind koji može učiniti puno pomoći. Možete pokrenuti program pod Valgrind kako bi se omogućilo opsežna provjera spremišta memorije izdvajanja i pristupa. Kada Valgrind otkrije problem, to vam daje neposredna, izravni podaci koji vam omogućuje da lakše pronaći i riješiti problem. Valgrind također izvješća o manje smrtonosnih memorijskih pitanjima, kao što su memorijske curenja, dodjele hrpa memorije, i zaboravljajući da ga oslobodi. Kao naš prevodilac, zveka, u našem debugger, gdb, Valgrind je slobodni softver, i to je instaliran na uređaj. Valgrind radi na vašem binarnom izvršnom, nije vaša. c ili. h izvorni kod datoteke, pa budite sigurni da ste sastavili up-to-date kopiju programa korištenje jeka ili napraviti. Zatim, prikazuju svoj program pod Valgrind može biti kao jednostavan kao samo prefiksa standardnu ​​programsku naredbu s riječju Valgrind, koji se pokreće Valgrind i pokreće program unutar njega. Prilikom pokretanja, Valgrind ne neki kompleks jiggering konfigurirati izvršnu za memorijske provjere, tako da se može uzeti malo da biste dobili gore i trčanje. Program će tada izvršiti normalno, bilo da se radi puno sporije, a kad završi, Valgrind će ispisati sažetak njegove memorije. Ako sve ide dobro, to će izgledati otprilike ovako: U ovom slučaju,. / Clean_program je put na programu želim pokrenuti. I dok to netko ne poduzimati nikakve argumente, ako je to učinio bih ih samo letati na kraju naredbe, kao i obično. Čisto program je samo glup mali program sam stvorio koje dodjeljuje prostor za blok Ints na hrpi, staviti neke vrijednosti unutar njih, i oslobađa cijeli blok. To je ono što snimate za, bez greške i bez curenja. Drugi važan podatak je ukupan broj bajtova dodijeljenih. Ovisno o programu, ako su vaši izdvajanja su u megabajta ili više, vjerojatno radite nešto krivo. Jeste li nepotrebno spremanje kopije? Koristite li hrpu za pohranu, kada bi bilo bolje koristiti stog? Dakle, memorijske pogreške mogu biti doista zlo. Što je više otvorenih one izazvati spektakularne ruši, ali čak i tada to još uvijek može biti teško odrediti što je točno dovelo do nesreće. Više podmuklo, program s memorijske greške još uvijek može sastaviti čisto i još uvijek se može činiti da rade ispravno zato što je uspio dobiti sretan većinu vremena. Nakon nekoliko uspješnih ishoda "," možda samo mislim da je sudar je slučajnost na računalu, ali računalo je nikada nije u krivu. Trčanje Valgrind može vam pomoći pronaći uzrok vidljivih memorije pogrešaka kao i pronaći vreba pogreške koje uopće ne još znati. Svaki put Valgrind otkrije problem, ispisuje informacije o tome što je to primijetio. Svaki predmet je prilično kratak - izvor linija prekršitelja nastave, u čemu je problem, i malo info o memoriji uključeni - ali često je dovoljno informacija da usmjeri svoju pozornost na pravom mjestu. Ovdje je primjer Valgrind trčanje na buggy programu da ne nevažeći pročitati hrpa memorije. Vidimo nema greške ili upozorenja u kompilaciju. Uh-oh, pogreška sažetak kaže da postoje dvije pogreške - dva nevažeća čita veličine 4 - bajtova, koji je. Oba loše čita dogodila u glavnom funkciji invalid_read.c, prvi na liniji 16 i drugi na liniji 19. Pogledajmo koda. Izgleda da je prvi poziv na printf pokušava pročitati jedan int prošlosti kraja našeg pamćenja bloka. Ako se osvrnemo na Valgrind je izlaz, vidimo da Valgrind rekao nam je da je točno. Adresa pokušavamo pročitati počinje 0 bytes prošlosti kraju bloka veličine 16 bajtova - četiri 32-bitne Ints da smo dodijeljeni. To je, adresa pokušavali smo čitati počinje pravo na kraju našeg bloka, Upravo kao što smo vidjeli u našem lošem printf poziva. Sada, nevažeći čita možda ne čini kao da je veliki posao, ali ako ste koristeći te podatke kontrolirati tijek svog programa - na primjer, kao dio ako izjava ili petlje - onda stvari tiho može ići loše. Pogledajte kako mogu pokrenuti invalid_read programa i ništa od običnih događa. Zastrašujuće, ha? Sada, pogledajmo neke više vrsta pogrešaka koje možete naići u svom kodu, pa ćemo vidjeti kako Valgrind ih otkrije. Upravo smo vidjeli primjer jednog invalid_read, pa sad ajmo provjeriti je invalid_write. Opet, nema pogreške ili upozorenja u kompilaciju. Ok, Valgrind kaže da postoje dvije pogreške u ovom programu - i invalid_write i invalid_read. Idemo provjeriti ovaj kod. Izgleda da smo dobili primjerak klasične strlen plus jedan bug. Kod ne malloc dodatni byte prostora za / 0 karaktera, pa kad str kopija otišao da ga pisati na ssubstrlen "cs50 stijena!" to je napisao jedan bajt prošlosti kraja našeg bloka. The invalid_read dolazi kada smo napraviti naš poziv na printf. Printf završi čitanje nevažeći pamćenje kad čita / 0 karakter kao što izgleda na kraju ovog niza E to je tisak. No, ništa od toga pobjegao Valgrind. Vidimo da je uhvaćen invalid_write kao dio str primjerku na liniji 11 glavna i invalid_read dio printf. Rock na, Valgrind. Opet, to ne može činiti kao veliki posao. Možemo pokrenuti ovaj program više i više izvan Valgrind i ne vidim nikakve simptome pogrešaka. Međutim, pogledajmo blagim varijacijama to vidjeti kako stvari mogu dobiti jako loše. Dakle, odobren, mi smo zloupotrebljavaju stvari više nego samo malo u ovom kodeksu. Mi samo ste dodjele prostora na hrpi za dvije žice duljina cs50 stijena, ovaj put, prisjećajući se / 0 karakter. Ali onda bacamo u super-dugi niz u memoriju blok da S pokazuje da. Što će učinak koji imaju na memorijsku blok koji ukazuje na T? Pa, ako je T ukazuje na memoriju koja je samo u susjedstvu S, dolaze tek nakon njega, tada smo mogli napisao preko dijelu T. Ajmo pokrenuti ovaj kod. Pogledajte što se dogodilo. Žice smo pohranjeni u našim spremišta blokova obje pojavili su tiskani ispravno. Ništa se čini u redu uopće. Međutim, vratimo se u naš kod i komentirati out liniju gdje smo kopirati cs50 stijene u drugom memorijskom bloku, istaknuo da su t. Sada, kada smo pokrenuti ovaj kod trebamo vidjeti samo sadržaj prve memorijske bloka isprintati. Opa, iako nismo str kopija bilo znakova u drugom hrpa bloka, jedan je istaknuo da je T, smo dobili ispis. Doista, niz mi punjena u našem prvom bloku pregazili prvi blok i u drugom bloku, čineći sve izgleda normalno. Valgrind, međutim, govori nam istinitu priču. Tu ćemo ići. Svi oni valjan čita i piše. Pogledajmo primjer druge vrste pogreške. Ovdje ćemo nešto napraviti, a nesretni. Mi zgrabite prostor za int na hrpi, i mi inicijalizirati pokazivač int - p - da pokazuje na tom prostoru. Međutim, dok je naš pokazivač inicijaliziran, podaci da je upućuju na upravo ono što je junk u tom dijelu hrpi. Dakle, kada smo učitali te podatke u int i, mi smo tehnički ja inicijalizirati, ali mi to učiniti s junk podataka. Poziv potvrditi, koji je zgodan za ispravljanje pogrešaka makro definirana u podesno zove tvrde knjižnici, će se prekinuti program ako je njegov ispitni uvjet ne uspije. To je, ako ja ne 0. Ovisno o tome što je u heap prostora, istaknuo p, ovaj program mogao raditi ponekad i uspjeti u drugim vremenima. Ako to radi, mi smo samo dobivanje sretan. Prevodilac neće uhvatiti tu pogrešku, ali Valgrind sigurni da će. Tu vidimo pogrešku koja proizlazi iz naše korištenje tog junk podataka. Kada izdvojiti hrpa memorije, ali ne drukčije pridijeliti ili ga osloboditi, koja se zove curenja. Za male, kratkotrajne programa koji traje i odmah izlaze, curi su prilično bezopasno, ali za projekt većih dimenzija i / ili dugovječnost, čak i mala curenja mogu udružiti u nešto duru. Za CS50, mi očekujemo da voditi brigu o oslobađanju sve hrpa memorije koju dodjeljujete, jer želimo izgraditi vještine za pravilno rukovanje postupkom ručnog zahtijeva C. Da biste to učinili, vaš program bi trebao imati točan jedan-na-jedan prepiska između malloc i besplatne pozive. Srećom, Valgrind može vam pomoći s memorijskim curenja previše. Ovdje je curi program koji se zove leak.c da dodijeli prostor na hrpi, piše na njega, ali ga ne oslobodi. Mi ga sastaviti sa Provjerite i pokrenite ga pod Valgrind, i vidimo da, dok nemamo memorijske pogreške, mi imamo jedan curenja. Postoji 16 bajtova definitivno izgubljena, što znači da je kazaljka na tom memorije nije bio u opsegu kada je program izašao. Sada, Valgrind ne daju nam tonu informacija o curenja, ali ako ćemo slijediti ovaj mali na umu da to daje dolje prema dnu svom izvješću na reprizu s - curenja provjerite = puni vidjeti sve pojedinosti o curenju memorije, ćemo dobiti više informacija. Sada, u heap sažetku, Valgrind nam govori gdje je memorija koja je izgubila prvobitno dodijeljena. Baš kao što znamo iz gleda u izvornom kodu, Valgrind nas obavještava da smo procurila memoriju dodjeljuje pozivom na malloc na liniji 8 od leak.c u glavnom funkciji. Prilično divan. Valgrind kategorizira curenja pomoću ove uvjete: Definitivno izgubili - to je gomila dodijeljena memorija na koje program više nema pokazivač. Valgrind zna da ste nekad imali pokazivač, ali od tada su izgubili pojam o tome. Ova memorija je definitivno procurila. Indirektno izgubili - to je gomila dodijeljena memorija na koje se samo upućuje na njega su također izgubili. Na primjer, ako ste izgubili svoj pokazivač na prvi čvor povezane liste, tada prvi čvor sama bi definitivno biti izgubljen, dok sve naknadne čvorovi bi posredno biti izgubljen. Možda izgubili - to je gomila dodijeljena memorija na koje Valgrind ne može biti siguran da li je pokazivač ili ne. Ipak dostupna je hrpa dodijeljena memorija na koje se program i dalje ima pokazivač na izlazu, što obično znači da je globalna varijabla ukazuje na to. Za provjeru tih curenja, također ćete morati uključiti opciju - Još uvijek dostupna = yes u zazivanjem Valgrind. Ti različiti slučajevi mogu zahtijevati različite strategije za njihovo čišćenje, ali curi bi trebao biti eliminiran. Nažalost, popravljajući curenje može biti teško za napraviti, od pogrešnih poziva na besplatno može raznijeti svoj program. Na primjer, ako gledamo invalid_free.c, vidimo primjer lošeg pamćenja deallocation. Što bi trebao biti jedan poziv da oslobodi cijeli blok memorije je istaknuo da po int_block, je umjesto postala pokušaj da se oslobodi svaki int veličine odjeljak sjećanja pojedinačno. To će uspjeti katastrofalno. Bum! Što pogreška. To definitivno nije dobro. Ako ste zapeli s tom vrstom pogreške, ipak, i vi ne znate gdje se mogu pogledati, padne natrag na svoj novi najbolji prijatelj. Pogodili ste - Valgrind. Valgrind, kao i uvijek, točno zna što je gore. U alloc i bez računa ne podudaraju. Imamo jednog alloc i 4 oslobađa. I Valgrind nam također govori gdje je prvi loš besplatan poziv - onaj koji pokreću Blowup - dolazi iz - linija 16. Kao što možete vidjeti, loši pozivi za free su stvarno loše, pa preporučujemo ostavljajući svoju programsku curenja dok radite na dobivanje funkcionalnost točne. Početak u potrazi za curenje tek nakon vaš program radi ispravno, bez ikakvih drugih pogrešaka. I to je sve što imam za ovaj video. Sada ono što čekate? Idi pokrenuti Valgrind na vašim programima upravo sada. Moje ime je Nate Hardison. Ovo je CS50. [CS50.TV]