[Powered by Google Translate] [Valgrind]
[Nate Hardison, Harvard University]
Això és CS50, CS50.TV]
Alguns dels errors més difícils en els programes en C
provenen de la mala gestió de la memòria.
Hi ha un gran nombre de formes d'enredar les coses,
incloent l'assignació de la quantitat incorrecta de la memòria,
oblidar inicialitzar variables,
escrit abans o després del final d'un tampó,
i l'alliberament de mantenir els temps de memòria múltiples.
Els símptomes van des fallades intermitents
als valors misteriosament sobrescrits,
sovint en llocs i temps molt allunyats de l'error original.
Rastrejant el problema observat de nou a la causa subjacent
pot ser un repte,
però, afortunadament, hi ha un programa anomenat útil Valgrind
que es pot fer molt per ajudar.
>> Executar un programa amb Valgrind perquè
comprovació extensa d'assignacions de memòria heap i accessos.
Quan Valgrind detecta un problema, se li dóna immediata,
informació directa que els permet
més fàcilment trobar i solucionar el problema.
Valgrind també informes sobre problemes de memòria menys mortals,
com ara pèrdues de memòria, assignació de memòria heap,
i oblidar-se de alliberar.
Com el nostre compilador, Clang, en el nostre depurador GDB,
Valgrind és programari lliure, i s'instal · la al aparell.
Valgrind s'executa en l'executable binari,
no teu. co. arxius d'origen h de codi,
així que assegureu-vos que vostè hagi compilat una còpia actualitzada al dia del seu programa
utilitzant Clang o fer.
A continuació, executa el programa sota Valgrind pot ser
tan simple com prefix el símbol del programa estàndard amb el Valgrind paraula,
que s'inicia Valgrind i executa el programa a l'interior de la mateixa.
En iniciar, Valgrind fa algun complex
jiggering per configurar l'executable de la vigilància a la memòria,
pel que pot trigar una mica per posar-se en marxa.
Llavors, el programa s'executarà normalment, poden ser molt més lentament,
i quan acaba, Valgrind imprimirà un resum del seu ús de memòria.
Si tot va bé, es veurà alguna cosa com això:
En aquest cas,. / Clean_program
és la ruta d'accés al programa que voleu executar.
I mentre això no es pren cap argument,
si ho fes jo acabava d'ells cap a la final de l'ordre com de costum.
Programa Clean és un programa poc ximple que he creat
que assigna espai per a un bloc d'enters en el munt,
posar alguns valors dins d'ells, i allibera tota la poma.
Això és el que vostè està tirant per, sense errors i sense fuites.
>> Una altra mètrica important és el nombre total de bytes assignats.
Depenent del programa, si les seves assignacions estan en megabytes o més,
vostè està probablement fent alguna cosa malament.
Estàs innecessàriament emmagatzemar duplicats?
Està utilitzant la pila d'emmagatzematge, quan seria millor fer servir la pila?
Per tant, els errors de memòria poden ser veritablement malament.
Els més evidents causar accidents espectaculars,
però tot i així, encara pot ser difícil d'identificar
exactament el que va conduir a la caiguda.
Pitjor encara, un programa amb un error de memòria
encara pot compilar netament
i encara pot semblen funcionar
perquè les hi va arreglar per tenir sort la major part del temps.
Després de diversos "resultats reeixits"
vostè podria pensar que un accident és un cop de sort de l'ordinador,
però l'equip mai s'equivoca.
>> Execució de Valgrind pot ajudar a localitzar la causa dels errors de memòria visibles
així com trobar l'aguait errors que ni tan sols encara coneixem.
Cada vegada Valgrind detecta un problema, es mostra informació sobre el que observa.
Cada article és bastant breu -
la línia de la font de la instrucció infractora, quin és el problema,
i una mica d'informació sobre la memòria involucrats -
però sovint és suficient informació per dirigir la seva atenció cap al lloc correcte.
Aquí és un exemple de Valgrind executa en un programa defectuós
que fa una lectura vàlida de la memòria heap.
No veiem els errors o advertències de compilació.
Uh-oh, el resum error diu que hi ha dos errors -
dues lectures invàlides de mida 4 - bytes, és a dir.
Tant dolenta llegeix produït en la funció principal de invalid_read.c,
el primer a la línia 16 i la segona en la línia 19.
Vegem el codi.
Sembla que la primera trucada a printf intenta llegir un int enllà del final del nostre bloc de memòria.
Si mirem cap enrere en la sortida de Valgrind,
veiem que Valgrind ens va dir exactament això.
La direcció que estem tractant de llegir comença 0 bytes
més enllà de l'extrem del bloc de mida 16 bytes -
quatre enters de 32-bit que ens assignen.
És a dir, l'adreça que estàvem tractant de llegir comença just al final del nostre bloc,
tal com veiem en la nostra crida printf dolent.
Ara, no és vàlid lectures no sembla ser tan gran d'un acord,
però si vostè està utilitzant aquestes dades per controlar el flux del programa -
per exemple, com a part d'una sentència if o loop -
llavors les coses poden anar malament en silenci.
Mira com puc executar el programa invalid_read
i res fora del comú passa.
Fa por, eh?
>> Ara, donem una ullada a alguns tipus més dels errors que poden sorgir en el codi,
i veurem com Valgrind els detecta.
Acabem de veure un exemple d'un invalid_read,
de manera que ara anem a veure un invalid_write.
Un cop més, no hi ha errors o advertències de compilació.
Bé, Valgrind diu que hi ha dos errors en aquest programa -
i invalid_write i invalid_read un arxiu.
Anem a veure aquest codi.
Sembla que tenim un exemple del clàssic strlen a més d'un error.
El codi no malloc un byte extra d'espai
pel caràcter / 0,
així que quan str còpia va ser a escriure en ssubstrlen "CS50 rocks!"
el va escriure un byte més enllà del final del nostre bloc.
El invalid_read ve quan fem la nostra crida a printf.
Printf acaba la lectura de memòria no vàlida quan es llegeix la / 0 caràcter
com es veu a l'extrem d'aquesta cadena E és impressió.
Però res d'això va escapar Valgrind.
Veiem que va cridar l'invalid_write com a part de la còpia de str
en la línia 11 de la principal, i la invalid_read és part de printf.
Rock on, Valgrind.
De nou, això no sembla ser un gran problema.
Podem executar aquest programa una i altra vegada fora de Valgrind
i no veu cap símptoma d'error.
>> No obstant això, anem a veure una lleugera variació d'això per veure
com les coses poden posar-se molt malament.
Així que, és cert, estem abusant de coses més que només una mica en aquest codi.
Només estem assignant espai a la pila de dues cadenes
la longitud de CS50 roques,
aquesta vegada, recordant la / 0 caràcters.
Però després llençar d'una cadena de super-llarga en el bloc de memòria
S que està apuntant.
Quin efecte tindrà això en el bloc de memòria que apunta a T?
Bé, si els punts de T a la memòria que hi ha just al costat de S,
ve just després d'ella,
llavors podríem haver escrit sobre part de T.
Anem a executar aquest codi.
Mira el que va passar.
Les cadenes s'emmagatzemen en els nostres blocs munt ambdós semblaven haver imprès correctament.
Res sembla gens malament.
No obstant això, tornem al nostre codi i
comentar la línia on copiem CS50 roques
en el segon bloc de memòria, a la qual apunta t.
Ara, quan executi aquest codi hem
només veure el contingut del primer bloc de memòria imprimir.
Whoa, encara que nosaltres no ho vam fer str còpia
els caràcters en el bloc munt segon, el apuntat per T,
obtenim una impressió.
De fet, la cadena es va ficar en el nostre primer bloc
envair el bloc primer i en el segon bloc,
fent que tot sembli normal.
Valgrind, però, ens explica la història real.
Aquí anem.
Tots aquells invàlid llegeix i escriu.
>> Vegem un exemple d'un altre tipus d'error.
Aquí fem alguna cosa bastant lamentable.
Agafem l'espai per a un sencer al heap,
i ens inicialitzar un punter int - p - per apuntar a aquest espai.
No obstant això, mentre que el nostre punter s'inicialitza,
les dades que s'està apuntant a només l'ha escombraries són en aquesta part de la pila.
Així que quan carreguem aquestes dades en int i,
que tècnicament i inicialitzar,
però ho fem amb dades de la ferralla.
La crida a afirmar, que és una macro de depuració pràctic
es defineix en el bé anomenat afirmar biblioteca,
avortarà el programa si la seva condició de prova falla.
És a dir, si no és 0.
Depenent del que havia en l'espai del munt, apuntat per p,
aquest programa pot treballar de vegades i no en altres moments.
Si funciona, només estem tenint sort.
El compilador no detectarà aquest error, però Valgrind voluntat segura.
Allà veiem que l'error resultant del nostre ús d'aquestes dades no desitjats.
>> En assignar memòria del munt, però no ho desassignar o alliberar-lo,
que es diu una fuita.
Per a un petit, efímer programa que s'executa i surt immediatament,
fuites són bastant inofensius,
però per a un projecte més gran i / o la longevitat,
fins i tot una petita fuita pot complicar en una cosa important.
Per CS50, esperem que
tenir cura d'alliberar tota la memòria heap que assigni,
ja que volem que vostè construeixi els coneixements necessaris per gestionar adequadament el procés manual
requerit per C.
Per això, el programa ha de tenir un exacte
un-a-un correspondència entre malloc i trucades gratuïtes.
Afortunadament, Valgrind pot ajudar amb les pèrdues de memòria també.
Aquí hi ha un programa anomenat fugues leak.c que assigna
espai a la pila, escriu-hi, però no l'alliberarà.
Ens compilar amb make i executar el programa sota Valgrind,
i veiem que, si bé no tenim errors de memòria,
tenim una fuga.
Hi ha 16 bytes definitivament perduts,
el que significa que el punter a la memòria que no estava en l'àmbit quan el programa es tanca.
Ara, Valgrind no ens dóna un munt d'informació sobre la fuga,
però si seguim aquesta petita nota que dóna cap al fons del seu informe
tornar a executar amb - Fuga-check = complet
per veure els detalls complets de memòria perduda,
obtindrem més informació.
Ara bé, en el resum munt,
Valgrind ens diu que la memòria que es va perdre va ser assignat inicialment.
Així com sabem de mirar al codi font,
Valgrind ens informa que va filtrar la memòria
assignat amb una crida a malloc a la línia 8 de leak.c
en la funció principal.
Bastant enginyós.
>> Valgrind classifica fuites usant aquests termes:
Definitivament perdut - això és la pila de memòria assignada
en què el programa ja no té un punter.
Valgrind sap que un cop va tenir el punter, però des de llavors han perdut la pista.
Aquesta memòria és, sens dubte filtrat.
Indirectament perdut - aquesta és la pila de memòria assignada
a la qual només els punters a què també es perden.
Per exemple, si vostè va perdre el seu punter al primer node d'una llista enllaçada,
llavors el primer node en si seria definitivament perdut,
mentre que els nodes subsegüents serien indirectament perdut.
Possiblement perdut - aquesta és la pila de memòria assignada
a la qual Valgrind no pot estar segur si hi ha un punter o no.
Encara és accessible la pila de memòria assignada
en què el programa encara té un punter a la sortida,
que significa típicament que apunta una variable global a aquesta.
Per comprovar si aquestes filtracions, vostè també haurà d'incloure l'opció
- Encara assolible = yes
en la seva advocació de Valgrind.
>> Aquests casos poden requerir diferents estratègies diferents per netejar,
però les fuites han de ser eliminats.
Malauradament, la fixació de les fuites poden ser difícil de fer,
ja que les trucades incorrectes a lliure pot explotar el seu programa.
Per exemple, si ens fixem en invalid_free.c,
veiem un exemple de desassignació mal record.
El que hauria de ser una sola trucada a alliberar tot el bloc
de memòria apuntada per int_block,
en canvi, s'ha convertit en un intent per alliberar cada secció de la mida d'int
de la memòria individualment.
Això fallarà catastròficament.
Boom! Quin error.
Això definitivament no és bo.
Si vostè està encallat amb aquest tipus d'error, però, i vostè no sap on buscar,
recórrer al seu nou millor amic.
Vostè ho va endevinar - Valgrind.
Valgrind, com sempre, sap exactament el que passa.
Els recomptes Alloc i lliure no coincideixen.
Tenim un Alloc i 4 lliura.
I Valgrind també ens diu que la primera trucada gratuïta dolent -
la que va desencadenar l'explosió - es ve -
la línia 16.
Com pot veure, les anomenades males per alliberar són realment dolentes,
el que es recomana deixar que la seva fugida programa
mentre que vostè està treballant en aconseguir el correcte funcionament.
Comenceu a buscar fuites només després que el seu programa està funcionant correctament,
sense altres errors.
>> I això és tot el que tenim per aquest vídeo.
Ara, què estàs esperant?
Anar executar Valgrind en els seus programes en aquests moments.
El meu nom és Nate Hardison. Això és CS50. [CS50.TV]