[Powered by Google Translate] [Valgrind] [Nate Hardison, Harvard Universiteit] Dit is CS50, CS50.TV] Sommige van die moeilikste foute in C-programme kom van die wanbestuur van die geheue. Daar is 'n groot aantal van maniere om dinge te skroef, insluitend die toekenning van die verkeerde bedrag van die geheue, vergeet veranderlikes te inisialiseer, skriftelik voor of na die einde van 'n buffer, en bevry hou geheue verskeie kere. Die simptome wissel van 'n onderbroke crashes geheimsinnig oorskryf waardes, dikwels op plekke en tye wat ver verwyderd van die oorspronklike fout. Die opsporing van die waargenome probleem terug na die onderliggende oorsaak kan wees uitdagend, maar gelukkig is daar is 'n nuttige program genaamd Valgrind wat kan 'n baie doen om te help. Jy 'n program onder Valgrind in staat te stel uitgebreide kontrolering van hoop geheue toekennings en toegange. Wanneer Valgrind ontdek 'n probleem, dit gee jou onmiddellike, direkte inligting wat u toelaat om meer maklik te vind en op te los die probleem. Valgrind ook verslae oor minder dodelike geheue, soos geheue lekkasies, die toekenning van hoop geheue, en vergeet om dit te bevry. Soos ons samesteller, klang, in ons debugger, GDB, Valgrind is gratis sagteware, en dit is op die toestel geïnstalleer. Valgrind loop op jou program uitvoerbaar, nie jou C of h bron kode lêers, so wees seker dat jy 'n up-to-date kopie van jou program saamgestel met behulp van kletteren of maak. Dan kan die bestuur van jou program onder Valgrind so eenvoudig as net die standaard program bevel met die woord Valgrind prefixing, wat begin op Valgrind en hardloop die program binnekant van dit. Wanneer jy begin, Valgrind sommige komplekse jiggering die uitvoer op te stel vir die geheue tjeks, sodat dit kan 'n bietjie te kry up and running. Die program sal dan normaalweg voer, word dit baie stadiger, en wanneer dit afwerkings, sal Valgrind print 'n opsomming van sy geheue gebruik. As alles goed gaan, sal dit lyk iets soos hierdie: In hierdie geval, / clean_program. is die pad na die program wat ek wil uit te voer. En terwyl hierdie een nie enige argumente, indien dit gedoen het Ek wil net ryg hulle op die einde van die opdrag soos gewoonlik. Clean program is net 'n dom klein program wat ek gemaak het wat ken ruimte vir 'n blok van ints op die hoop, sit 'n paar waardes binnekant van hulle, en bevry die hele blok. Dit is wat jy skiet, geen foute en geen lekkasies. Nog 'n belangrike maatstaf is die totale aantal grepe wat toegeken. Afhangende van die program, indien u toekennings is in die megagrepe of hoër, is jy waarskynlik doen iets verkeerd. Is jy onnodig stoor duplikate? Is jy met behulp van die hoop vir die stoor, wanneer dit beter sou wees om die stapel te gebruik? Dus, kan die geheue foute werklik kwaad. Die meer openlike skouspelagtige ineenstortings veroorsaak, maar selfs dan kan dit nog steeds moeilik wees om vas te stel wat presies tot die ongeluk gelei het. Meer slinkse wyse, 'n program met 'n geheue fout kan nog steeds skoon stel en kan nog steeds blyk korrek te werk omdat jy gelukkig die meeste van die tyd te kry. Na 'n paar "suksesvolle uitkomste," jy mag dalk net dink dat 'n ongeluk is 'n gelukskoot van die rekenaar, maar die rekenaar is nooit verkeerd nie. Running Valgrind kan jou help om die oorsaak van sigbare geheue foute opspoor sowel as loer foute jy selfs nog nie weet nie. Elke keer Valgrind ontdek 'n probleem is, is dit druk inligting oor wat dit waargeneem. Elke item is redelik kortaf - die bron lyn van die gewraakte onderrig, wat die probleem is, en 'n bietjie inligting oor die geheue wat betrokke is - maar dikwels is dit genoeg inligting om jou aandag te rig op die regte plek. Hier is 'n voorbeeld van Valgrind loop op 'n buggy program wat nie 'n ongeldige lees van hoop geheue. Ons sien geen foute of waarskuwings in die samestelling. Uh-oh, die fout opsomming sê dat daar twee foute - twee ongeldig gelees van grootte 4 - bytes, dit is. Slegtes sowel lees plaasgevind het in die hooffunksie van invalid_read.c, die eerste on line 16 en die tweede on line 19. Kom ons kyk na die kode. Lyk soos die eerste oproep tot printf probeer een int verby die einde van ons geheue blok te lees. As ons terugkyk op Valgrind se uitset, sien ons dat Valgrind vertel ons presies dit. Begin die adres wat ons probeer om te lees 0 bytes verby die einde van die blok van grootte 16 bytes - vier 32-bis ints dat ons toegeken. Dit is die adres wat ons probeer om te lees begin reg aan die einde van ons blok, net soos ons sien in ons slegte printf oproep. Nou, kan ongeldig gelees nie lyk dat die groot van 'n deal, maar as jy die gebruik van daardie data om die vloei te beheer van jou program - byvoorbeeld, as deel van 'n IF-stelling of lus - dan kan dinge stil gaan sleg. Kyk hoe ek dit kan die invalid_read program hardloop en niks uit die gewone gebeur. Scary, huh? Nou, laat ons kyk na 'n paar meer soorte foute wat jy kan teëkom in jou kode, en ons sal sien hoe Valgrind ontdek hulle. Ons het net gesien 'n voorbeeld van 'n invalid_read, so laat ons nou kyk na 'n invalid_write. Weereens, geen foute of waarskuwings in die samestelling. Okay, Valgrind sê dat daar twee foute in hierdie program - en invalid_write en 'n invalid_read. Kom check hierdie kode. Lyk my ons het 'n geval van die klassieke strlen plus een fout. Die kode nie malloc 'n ekstra greep van die ruimte vir die / 0 karakter, so wanneer str kopie het om dit te skryf ssubstrlen "cs50 rotse!" dit het geskryf 1 byte verby die einde van die blok. Die invalid_read kom wanneer ons ons oproep om printf. Printf beland ongeldig geheue te lees wanneer dit lees / 0 karakter as dit lyk aan die einde van hierdie E-string is dit druk. Maar geeneen van hierdie ontsnap Valgrind. Sien ons dat dit gevang die invalid_write as deel van die str afskrif on line 11 van die hoof, en die invalid_read is deel van printf. Rock, Valgrind. Weereens, kan dit nie lyk soos 'n groot deal. Ons kan hierdie program oor en oor loop buite Valgrind en nie sien nie enige fout simptome. Maar, laat ons kyk na 'n effense variasie van hierdie om te sien hoe dinge kan kry regtig sleg is. So, toegestaan ​​word, is ons misbruik dinge meer as net 'n bietjie in hierdie kode. Ons is net die toekenning van ruimte op die hoop vir twee stringe die lengte van cs50 rotse, hierdie tyd, onthou die / 0 karakter. Maar dan moet ons gooi in 'n super-lang string in die geheue blok dat S wys. Watter effek sal dit op die geheue blok dat T punte? Wel, as T punte te geheue wat net aangrensend aan S, kom net nadat dit, dan kan ons geskryf het oor die deel van T. Kom ons gebruik hierdie kode. Kyk na wat gebeur het. Die stringe wat ons in ons hoop blokke beide gestoor verskyn het korrek uitgedruk. Dit lyk asof niks verkeerd is nie. Maar laat ons gaan terug in ons kode en kommentaar uit die lyn waar ons cs50 rotse kopieer in die tweede geheue blok, wys deur t. Nou, wanneer ons gebruik hierdie kode moet ons sien net die inhoud van die eerste geheue blok druk. Whoa, selfs al het ons nie str afskrif enige karakters in die tweede hoop blok, die een wys deur T, kry ons 'n druk uit. Trouens, die tou wat ons in ons eerste blok gestop oorrompel die eerste blok en in die tweede blokkie, maak alles lyk normaal. Valgrind, maar, vertel die ware verhaal. Daar gaan ons. Al dié ongeldig lees en skryf. Kom ons kyk na 'n voorbeeld van 'n ander soort van fout. Hier het ons iets doen nogal jammer. Ons gryp ruimte vir 'n int op die hoop, en ons inisialiseer 'n int pointer - p - om te verwys na daardie ruimte. Maar, terwyl ons wyser is geïnisialiseer word, die data dat dit verwys na net watter gemors is in daardie deel van die hoop. So wanneer ons laai dat die data in int i, ons tegnies inisialiseer i, maar ons doen dit met junk data. Die oproep om te beweer, wat is 'n handige debugging makro omskryf in die welverdiende naam beweer biblioteek, sal staak die program as sy toets toestand misluk. Dit is, as ek is nie 0. Afhangende van wat was in die hoop ruimte, wys deur p, hierdie program kan soms werk en versuim om op ander tye. As dit werk, ons is maar net gelukkig. Die opsteller sal nie hierdie fout vang, maar sal seker Valgrind. Daar sien ons die fout wat spruit uit die gebruik van daardie junk data. Wanneer jy toeken hoopgeheue, maar deallocate dit nie of vry, wat genoem word 'n lek. Vir 'n klein, kortstondige program wat loop en onmiddellik uitgange, lekkasies is redelik skadeloos, maar vir 'n projek van die groter grootte en / of lang lewe, selfs 'n klein lek kan vererger in iets groot. Vir CS50, verwag ons om jou te sorg bevry van al van die hoop, geheue wat jy toeken, omdat ons wil hê dat jy die vaardighede op te bou om behoorlik die handleiding proses hanteer vereis deur C. Om dit te doen, moet jy jou program 'n presiese een-tot-een korrespondensie tussen malloc en gratis oproepe. Gelukkig kan Valgrind u help met die geheue lekkasies. Hier is 'n lekkende program genaamd leak.c wat ken ruimte op die hoop, om dit te skryf, maar nie vry om dit. Ons stel dit met Maak en hardloop onder Valgrind, en ons sien dat, terwyl ons het geen geheue foute, ons het 'n lek. Daar is 16 bytes beslis verlore, wat beteken dat die wyser na daardie geheue was nie in omvang toe die program opgewonde. Nou, Valgrind nie gee ons 'n ton van die inligting oor die lekkasie, maar as ons hierdie klein daarop dat dit gee af na die onderkant van sy verslag rerun met - lek-check = volle die volle besonderhede van die geheue gelek te sien, ons kry meer inligting. Nou, in die hoop opsomming, Valgrind vertel ons waar die geheue wat verlore was aanvanklik toegeken. Net soos ons weet uit te kyk in die bronkode, Valgrind weet ons dat ons die geheue gelek toegeken met 'n oproep tot malloc on line 8 van leak.c in die hooffunksie. Pretty nifty. Valgrind kategoriseer lekkasies deur gebruik te maak van hierdie terme: Beslis verloor - dit is 'n hoop toegeken geheue wat die program het nie meer 'n wyser. Valgrind weet dat jy eens gehad het die wyser, maar het sedertdien verlore spoor van dit. Hierdie geheue is beslis uitgelek het. Indirek verloor - dit is 'n hoop toegeken geheue wat die enigste verwysings na dit ook verlore. Byvoorbeeld, as jy verloor jou muis na die eerste nodus van 'n geskakelde lys, dan is die eerste node self sal beslis verlore gaan, terwyl enige daaropvolgende nodes sou indirek verlore wees. Moontlik verloor - dit is 'n hoop toegeken geheue waarin Valgrind nie seker kan wees of daar is 'n aanwyser of nie. Nog bereikbaar is hoop toegeken geheue wat die program nog 'n wyser by die uitgang, wat beteken gewoonlik dat 'n globale veranderlike dui daarop. Om te kyk vir hierdie lekkasies, sal jy ook die opsie om te sluit - Nog bereikbaar = ja in jou aanroeping van Valgrind. Hierdie verskillende gevalle kan vereis verskillende strategieë vir die skoonmaak van hulle, maar lekkasies moet uitgeskakel word. Ongelukkig kan tot vaststelling van lekkasies moeilik wees om dit te doen, aangesien verkeerde oproepe gratis kan blaas jou program. Byvoorbeeld, as ons kyk by invalid_free.c, sien ons 'n voorbeeld van slegte geheue deallocation. Wat moet 'n enkele oproep om die hele blok te bevry geheue verwys na deur int_block, het eerder 'n poging om elke int-grootte artikel te bevry van die geheue individueel. Dit sal katastrofaal misluk. Boom! Wat 'n fout. Dit is beslis nie goed nie. As jy vas met hierdie soort van fout, al is, en jy weet nie waar om te kyk, om terug te val op jou nuwe beste vriend. Jy het reg geraai - Valgrind. Valgrind, soos altyd, weet presies wat is. Die alloc en gratis tellings stem nie ooreen nie. Ons het 1 alloc en 4 FreeS. En Valgrind vertel ons ook waar die eerste slegte gratis oproep - die een wat aanleiding tot die Perspectief aanpassen - is afkomstig van - lyn 16. Soos jy kan sien, slegte oproepe te bevry is regtig sleg, Daarom raai ons jou laat jou program lek terwyl jy werk om die funksie korrek is. Begin soek vir lekkasies slegs nadat jou program korrek werk nie, sonder enige ander foute. En dit is al wat ons gekry het vir hierdie video. Nou wat is jy wag vir? Gaan loop Valgrind op jou programme nou. My naam is Nate Hardison. Dit is CS50. [CS50.TV]