[? DONEN ARMADARAS :?] Hola, Estic [? Donen Armadaras?]. Avui, anem a es busca en la depuració. No només anem a parlar d'algunes tècniques, sinó que també anem a mirar algunes de les característiques contingudes dins de l'IDE CS50 que permeten depurar fàcilment un programa. Només un exemple de cosa que pot sortir malament i de fet és una cosa que ja hem vist abans. En aquest cas, aquest és un programa C que accepta un nombre enter d'usuari, el divideix per dos, i proporciona la sortida de nou a l'usuari. Ara del que hem vist anteriorment en conferències, sabem que això causarà tipus específics de problemes de divisió quan tenim números imparells. En concret, només haurem que llencem res després de la coma decimal. Ara, sabem que aquest passa a ser el cas. I si correm, podem confirmar les nostres sospites, primer, per la compilació. I després, corrent i entrar en un nombre imparell. Això no és res de nou. Però això és en realitat un exemple d'un error que pot existir dins d'un programa més ampli que es converteix en més difícil de rastrejar. Tot i que sabem quin és el problema és a dir, el veritable quid de la qüestió podria tractar d'identificar específicament on es produeix l'error, identificar el que aquest problema és, i després arreglar-ho. Així que oferir això com un exemple del que podria ser alguna cosa que ja sabem, però pot ser enterrat dins d'altres elements del codi. Per tant l'obertura d'aquesta altra font arxiu de codi com un exemple, aquest problema de divisió és ara part d'un programa més ampli. Encara podria ser una mica poc artificial, i nosaltres podria ser capaç de facilitat identificar-lo, especialment ja que només estem discutint això. Però podem imaginar que aquesta problema pot existir en una escala més gran. Si Va compilar això i ara executar, introduïu un nombre imparell, podem veure que no obtenim precisament la sortida que podem haver esperat. En aquest cas particular, podríem dir que ens volen comptar tots els números des d'un fins algun número específic. I podem veure que tenir una varietat de temes aquí si estem sortida, simplement, 0 i 1 quan proporcionem una entrada de 5. Així que ja sabem que hi ha un problema aquí. Però no podem saber amb precisió on aquest problema realment existeix. Ara una de les formes en què podem tractar de fer això és una cosa que hem ja s'ha introduït a. Només podem usar-lo en una escala més gran. En la línia 14, que tenim aquesta funció printf, el que ens permet imprimir l'estat de diverses peces d'informació. I això és una cosa que vostè ha d'aprofitar dins del seu programa per intentar esbrinar exactament el que és succeint en diverses línies de codi. Així que fins i tot si aquest no és el sortida final que en realitat voler produir de aquest programa, encara podrien tenir certa depuració declaracions on ens pot tractar d'esbrinar exactament el que està succeint dins del nostre codi. Així que en aquest cas, ho faré printf amb l'etiqueta de depuració. En aquest cas, això és només una cadena de depuració que estic fins desagradable perquè es converteixi molt clar en la sortida de la meva codi què és el que vull mostrar. I aquí el nombre de sortida que hem calculat. En aquest cas, podria digui de forma precisa el que està passant abans i després d'un càlcul específic. Així que jo podria utilitzar un printf abans i després d'aquesta línia de codi. En aquest cas, podria fins i tot que sigui una mica més clara dient depuració abans i depuració després de tant que jo no confonc a mi mateix amb múltiples línies que semblen idèntics. Ara bé, si a compilar i executar aquest ella, entrar un nombre com de cinc més, podem veure que tenim ara de sortida abans i després de i trobem que no hem fet una clara divisió o transparent que té el nombre que en realitat volem fer. Ara bé, en aquest cas, es tracta de no és realment una sortida clara. En realitat no és un resultat clar que volem sortir d'aquest programa en particular. I això és, de nou, un poc artificial. Però, potser, una de les coses que que podríem fer si l'especificació dir que volem dividir això 2 i afegir 1-- pel que en altres paraules, volem arrodonir up-- continuació podríem saber que vam poder fer aquesta cosa en particular, en aquest cas. Ara, aquí sabem que serem capaç de sumar 1 al nostre número reduït a la meitat. Anem a recompilar aquest i confirmar que aquesta es comporta de la manera que volem. Podem veure que ara abans que tenir, tenim el número 5. Després de tenir, tenim el número 3, que d'acord amb la nostra especificació, és el que volíem fer. Però si ens fixem en el sortida d'aquí, podem veure que podríem tenir una altra error per complet, que és que estem començant nostre compte des de 0. Ara, de nou, això és una cosa que hem vist en el passat i podem fixar amb força facilitat. Però en aquest cas, També tenia l'avantatge d'utilitzar la instrucció printf directament a l'interior del bucle for saber amb precisió on que l'error estava passant. Declaracions Així printf són molt útil per ajudar a determinar on, precisament en el seu codi font, s'està produint un error específic. I també és important tenir en compte que, com estem programant, podríem tenir supòsits sobre l'estat d'un programa. O pot ser que tinguem supòsits sobre quina part del programa és realment correcte o incorrecte quan més endavant a mesura que construïm en aquest programa i que sigui part d'un complex i més gran programa que ens adonem que algun aspecte que és en realitat buggy. L'ús de printf realment pot ajudar delimitar i identificar les regions d'un programa que no pot es comporta exactament de la manera que nosaltres esperar que, amb base en les nostres suposicions. Però hi ha altres eines disponibles, així, que ens permeten tractar d'entendre on s'està produint un error i també, específicament, quines coses estan succeint dins del programa. Així que fent servir printf és molt quan volem útil per identificar les àrees específiques de un programa que té alguns errors. Però també es converteix avorrit després d'un temps. En aquest cas, es tracta d'una programa relativament simple amb només una o dues variables. I es fa molt fàcil per a nosaltres imprimir el valor d'aquestes variables en el context del programa més gran. Però podríem tenir un diferent programa que té moltes variables. I pot no ser prou tan fàcil d'usar printf per tractar d'avaluar el que està succeint a cadascuna d'aquestes variables ja que el programa s'està executant. Hi ha un programa que existeix anomenat un programa depurador. En aquest cas, el que ho farem ús és el depurador de GNU, o GDB, que ens permet inspeccionar l'interior funcionament d'un programa en una forma molt més manera detallada. De fet, podem executar BGF des de la línia d'ordres aquí simplement escrivint el BGF i ​​la comandes que volem depurar. En aquest cas, explicar. Ara bé, en aquest cas, podem veure que ens porta a un missatge que diu GDB. I podem realitat executar comandaments de GDB per començar realment l'execució de la programa, detenir-lo en certs punts, avaluar les variables i inspeccionar les variables que existir en l'estat del programa en aquest moment particular, i així successivament i així successivament. Proporciona una gran quantitat d'energia per a nosaltres. Però dóna la casualitat que l'IDE CS50 també proporciona una interfície gràfica d'usuari o d'un usuari interfície perquè GDB ens permet fer això sense necessitat la interfície de línia d'ordres en absolut o en tot fins i tot. La forma en què jo pugui accedir a aquesta és mitjançant el botó de depuració a la part superior de l'IDE CS50. Ara bé, en el passat, el que tenim vist és que usem la comanda line per compilar i executar un programa. El botó de depuració fa dos d'aquests passos. Però també s'obre la pestanya depurador a l'extrem dret que ens permet inspeccionar una varietat de les propietats del programa ja que s'està executant. Si faig clic depuració, en aquest cas, s'obrirà una nova pestanya a la consola finestra a la part inferior. I es pot veure que aquesta fitxa té una mica d'informació a la part superior. I podem ignorar en gran mesura això. Però una de les coses que volem notar és que emet el mateix que nosaltres obtindria si tractem de fer funcionar el el programa de C a la finestra de terminal. Aquí, podem veure que s'està executant so metàl·lic, i té una varietat de banderes, i s'està recopilant nostre arxiu count.c, que va ser la fitxa seleccionada en el moment que em va colpejar de depuració. Així que això és molt útil perquè ara amb aquest botó de depuració, podem recopilar de forma simultània i després executar el programa que en realitat que desitgi executar. Un dels indicadors que es important, en aquest cas, que en realitat hem estat utilitzant per al temps més llarg sinó que també acaba de fer una mica de la mà agitant [inaudible], que és aquesta d'aquí. En Clang, diu -ggdb3. En aquest cas, el que som dient so metàl·lic, el nostre compilador, és que volem compilar el nostre programa. Però també proporcionar el que són anomenada informació de símbols perquè el compilador en realitat té accés a una gran quantitat de la informació subjacent continguda dins del programa. Més específicament, el nombre de les funcions que tinc, els noms de les funcions, les variables, els tipus que aquestes variables són, i una varietat d'altres coses que ajuden a que el depurador realitzar la seva operació. Ara hi ha alguna cosa més això és important esmentar quan estem discutint en execució un programa d'aquesta manera. Recordeu que no té realitat criat una nova pestanya en la nostra consola al llarg de la part inferior. Ja no ens enfrontem directament amb la finestra de terminal. Però aquesta nova pestanya és en realitat una finestra de terminal. Només és específic per al funcionament programa que hem creat. Observi que en la part inferior, en combinació amb alguna sortida per Clang el compilador i el BGF, que podem ignorar en gran mesura, que en realitat mostra la sortida de nostre programa a la part inferior. Ara és important tenir en compte que aquesta en realitat una finestra li mostrarà la sortida del seu programa però també pot acceptar l'entrada per a aquest programa, també. Així avís que indica si us plau escriu un nombre, que és la mateixa sortida que teníem tenia a la finestra de terminal abans. Però es mostra ara en aquesta nova pestanya. Em pot introduir un número. I ho farà realitat funció que esperem mostrant-nos la nostra depuració, la producció, la sortida que podria ser amb errors, com hem vist abans. I a la part inferior, es en realitat té una sortida addicional del PIB només dir que aquest programa s'ha completat. Ara bé, com es va veure en aquest en particular cursa a través de, no era particularment útil perquè fins i tot tot i que havia arribat el menú depurador dalt, això era encara un programa en execució. En cap moment va fer realitat aturar l'execució per a nosaltres ser capaç d'inspeccionar tots les variables contingudes dins. Hi ha alguna cosa més que hem de fer per per obtenir GDB reconèixer que volem per aturar l'execució del programa i no només permetre que es procedeixi normalment com ho faríem en qualsevol altre cas. Per tal d'aturar l'execució, en algun línia específica, hem de crear el que és anomenat un punt d'inflexió. I un punt d'inflexió es crea amb molta facilitat en aquest CS50 IDE prenent el punter del ratolí i fent clic directament a l'esquerra d'un número de línia específic. Una vegada que ho faig, un punt vermell apareix, que indica que aquesta línia és ara un punt d'inflexió. I la propera vegada que corro GDB, que s'aturarà l'execució en aquest punt de ruptura quan arriba a aquesta línia de codi. Ara bé, aquest és un important és adonar- que no és necessàriament el cas que cada línia de codi és realment accessible. Si hagués de crear una funció aquí, per exemple-- buit F-- i acaba de fer una línia d'impressió aquí-- hola món-- si no torno a trucar a aquesta funció, serà el cas que, si em vaig posar un punt de descans aquí, la funció mai es dirà. I per tant, aquest en particular punt d'inflexió serà en realitat mai fer una pausa execució del programa. Així que diguem que jo crec correctament un punt d'inflexió en alguna línia de codi que realment s'executa. Ara bé, en aquest cas, aquest és el primera línia de la funció principal. Així que sens dubte serà el cas que, tan aviat com començo execució, s'arribarà a la primera línia. GDB s'aturarà l'execució. I després, seré capaç de interactuar amb el depurador. Podeu establir diverses línies com punts de ruptura, si vol. També podem crear una línia cap amunt aquí en aquest segment de codi això mai s'aconseguirà. I també podem establir un més endavant. La raó que ho faríem voler fer això anem a entrar en una mica més detall en un moment. Així que per ara, permetin-me inhabilitar aquests punts de trencament addicionals perquè puguem veure el que succeeix quan tinc una sola ruptura punt del meu programa. He fet alguns canvis en aquest programa. Així que he de guardar-lo. Vaig a fer clic de depuració perquè jo pugui començar la compilació i després execució del depurador. Anem a veure que, després de moments, els línia que hem seleccionat com el descans punt es ressalta en groc. També podem notar que en el superior dreta del panell de depuració que la icona de pausa s'ha convertit en una petita icona de reproducció. Això vol dir que hem de fer una pausa execució, en aquest cas particular. I colpejar el botó de reproducció es ens permet reprendre l'execució en aquest punt específic. Observi que hi ha un parell d'altres botons disponibles en aquest panell de depuració, tant be. Passar per sobre, el que em permet executar que una línia de codi i passar per sobre d'aquesta línia a la següent, que, en aquest cas, que significaria que el printf s'executa comunicat. I a continuació, farà una pausa l'execució de la línia 13, com a tal. I hi ha també un pas en funció, que és útil si he creat una altra funcions en el codi font en altres llocs. I vull entrar en aquestes funcions en lloc de executar aquesta funció com un tot. Però anem a veure més en el pas en funció en un moment. Ara noti algunes altres coses que realment existir dins d'aquest panell de depuració. Tenim aquest panell anomenat Pila de trucades, el que ens mostra on exactament que som. En aquest cas, estem dins de la funció principal. El nostre script es diu count.c. I ens toca estar en línia 13, columna un, que és precisament el que la regió ressaltada del codi font indica, també. Ara noti que això demostra també a la secció variable local totes les variables que existir dins d'aquesta funció. És important tenir en compte que totes les variables apareixerà en aquesta variable local secció dins d'una funció, fins i tot abans que es defineixen. Podem veure aquí que tenim una variable anomenada num, té un valor predeterminat de 0, i és de tipus int. Ara abans que realment inicialitzem totes aquestes variables, no estem necessàriament garantit per veure un valor de 0. I depenent d'altres execucions que ha realitzat i l'estat de la seva memòria quan en realitat s'executa aquest programa, vostè podria trobar que vostè no veuen els valors de 0 i, en canvi, alguns altres números de bojos. Però no et preocupis per això. No va ser rellevant fins que realment inicialitzar el valor. Ara bé, en aquest cas, podem veure que He fet algunes sortides. I estic, ara mateix, vaig aturar l'execució. Però en aquest cas, el Tinc moltes ganes de fer és fer un pas ara sobre aquesta línia de codi perquè pugui realment consultar l'usuari per a aquest int que volem utilitzar en el nostre programa. Ara bé, en aquest cas, quan Vaig colpejar passar per sobre, previ avís que la pausa o més aviat la represa botó ha canviat a aquest botó Pausa ja que aquest codi s'executa en realitat. Que està passant en aquest moment és que es tracta esperant per nosaltres per introduir alguna informació com podem veure pel nostre text de sortida a la part inferior. Així que ara mateix, això és en realitat no es va aturar, tot i que, en certa manera, sembla ser perquè res està succeint. Però dóna la casualitat que en meu cas concret en la línia 13, Estic esperant a l'entrada de l'usuari. I així BGF no és capaç d'inspeccionar un programa a mida que s'està executant. Ara, la propera vegada que entro en alguna input-- així que vaig a entrar en aquest número 5, com hem vist en el past-- prem Intro, i nosaltres notar que, immediatament, pauses GDB i, de nou, es destaca la següent línia. Però cal notar que ara, com un resultat de la nostra ingressar un valor, hem actualitzat aquest valor a l'interior de les nostres variables locals, que és molt útil saber amb precisió el que aquest nombre era a la memòria. Ara puc permetre que aquest programa continuï jugant fins al final de la seva execució prement Reprendre. Podem veure que molt ràpidament fa l'acabat programa en execució amb la mateixa sortida que ens tingut abans, el depurador es tanca, i ara aquest programa s'ha aturat completament. Mostro que només per al efectes de veure el que que succeeix quan en realitat ens colpegem Reprendre. Però que en realitat anem a vull tornar a aquest programa perquè puguem tractar de depuració precisament el que està succeint. Ara que estic utilitzant el depurador, m'ho permet no necessita aquestes declaracions de depuració printf. Així que podria eliminar-los com faré ara acaba de tornar al nostre codi més simple que teníem fa un moment. Ara, quan m'estalvio el programar i executar-lo, serà, de nou, anar a aquesta inicial trencar el punt que jo tenia a la línia 11. I seré capaç d'inspeccionar la meva variables com ho volen fer. El que passa és que aquesta part no és molt interessant, I sé que vaig imprimir aquesta declaració. Si us plau, introdueixi un nombre. I després, sé que vaig preguntar a l'usuari per aquest nombre sencer. Així que potser, jo en realitat vull moure el meu punt de trencar una mica més avall. Podeu eliminar punts de trencament fent clic, de nou, directament a l'esquerra d'aquest número de línia. Aquest punt vermell desapareixerà, indicant que aquest punt de ruptura s'ha anat. Ara bé, en aquest cas, execució està en pausa. I el que no és en realitat va a reprendre en aquest cas particular. Però puc configurar un descans apuntar una mica més tard. I quan Reprenc ara la meva codi, es reprendrà i comptar al punt que el punt d'inflexió. Un cop més, em va colpejar a Reprèn. No sembla res està succeint. Però això és perquè el meu codi està a l'espera per a l'entrada. Vaig a introduir un nombre 5, premeu Enter, i Ara es va donar en el següent punt de ruptura. Ara, en aquest cas, aquesta és la línia de codi que, abans, sabíem va passar a ser buggy. Així que anem a avaluar el que succeeix en aquest punt particular en el temps. Quan es ressalta una línia, aquesta línia encara no ha estat executat. Així que en aquest cas, podem veure que tinc un número, que Tinc un sencer anomenat num que té un valor de 5. I jo vaig a realitzar una mica de matemàtica en aquest nombre. Si em pas més d'això, podem notar que el valor de num ha canviat d'acord amb el aritmètica que realment hem fet. I ara que estem dins d'aquest bucle o ara que el bucle for sí està ressaltat, veiem que tenim una nova variable i crida que va ser utilitzat en aquest bucle. Ara recordar abans que jo esmentar que a vegades ets anar a veure algun tipus de bogeria números per defecte abans d'aquest número o aquesta variable és en realitat inicialitzat. Podem veure que, precisament, aquí a la aquesta variable anomenada I, que no té però, ha inicialitzat en el moment de posar en relleu. Però podem veure que té un nombre que no anàvem realment esperar. Està bé. No es preocupi perquè tenim en realitat no inicialitzat aquest nombre fins que passar per sobre d'aquesta línia i el valor I ha estat inicialitzat amb el valor 1. Així que a veure que això és en realitat el cas, anem a passar per sobre. Ara podem veure que aquest línia ha estat executada. I ara estem destacant aquesta línia printf. I ara podem veure com els nostres valors d'i i 3 he canviat amb el temps. Això és molt útil per fer, de fet, és passar per sobre de les línies en diverses ocasions. I vostè pot trobar el que realment que succeeix dins del seu bucle for i el que li passa a la les variables dins d'aquest bucle for com que l'execució del programa es produeix un pas a la vegada. Ara, en aquest punt, va passar per sobre del que és just que ara estic al final del meu programa. Si em pas més d'això, ho farà de fet cessar l'execució com hem vist en el passat. Permetin-me recomençament això, un cop més, de manera que que puc assenyalar alguna cosa més, tant be. En aquest cas, és ara em demana, una vegada més, per a un nombre, el qual Jo, de nou, entrar. Però aquesta vegada, vaig a entrar en un nombre més gran perquè el bucle for iterará més vegades. En aquest cas, em vaig per introduir un valor d'11. Ara, de nou perquè em vaig posar un punt de trencament en la línia 15, es posarà en relleu aquesta línia. Podem veure que el nostre número 11 és correcta representat en les nostres variables locals. Passant per sobre d'això, podem ara observa el que succeeix al nostre valor d'i a mesura que avancem en l'interior d'aquest bucle. Es posa s'incrementa cada vegada que arribar al cim d'aquest bucle. Ara una de les coses que podria ser útil per fer durant l'execució d'aquest programa és per a mi realment canviar el mitjà del corrent de variables per veure el que passa al meu programa. En aquest cas, no puc realment feu doble clic al valor. Observi que es converteix en un camp de text. Ara puc entrar en diferent valorar completament per veure com es comporta el meu programa quan he canviat aquesta variable. Ara, en aquest cas, la variable i ara conté el valor 10. Però el programa segueix sent pausa en l'execució. Quan faig un pas més, veig que la i valor, que vaig entrar al 10, no és més gran que el valor de num, que immediatament fa que el bucle for per aturar l'execució. Ara això no és l'únic raó per la qual ho faria voler definir la variable al seu lloc. Vostè pot ser que realment vol per intentar modificar-lo per que pot continuar execució d'un bucle o perquè vostè pot ajustar algun valor abans que es arriba a un conjunt específic de l'aritmètica que està a punt de realitzar. Així que ara que en realitat canviem el valor d'i que el programa s'executa, va causar el bucle for per deixar de fumar prematurament perquè, de sobte, em va passar a ser major que el valor de num, el que significa que aquest bucle for ja no és necessari per a ser executat. A més, va passar a ser el cas que canviem el valor d'i quan es va posar en relleu la línia 17, que era el punt en el temps perquè l'execució del bucle va ser en realitat s'està avaluant. Si jo hagués canviat el valor de I en una línia diferent, dic 19, hauríem vist diferent comportament perquè la línia 19 ho faria haver executat abans del bucle condició va ser reevaluado. Ara en aquest moment, estic, de nou, al final d'aquest programa. I puc permetre que això continuï amb permeti que el meu programa per deixar de fumar de forma natural. Però hi ha un parell de coses que són importants per a dur d'aquesta discussió particular. Cal avaluar les seves pròpies suposicions sobre com el codi ha de ser comportant. Cada vegada que vostè pensa que alguna peça de codi que saps passa a treballar, que podria ser una bandera vermella per anar enrere i avaluar, i assegureu-vos que assumit com aquest codi està funcionant és realment fidel a la forma en què és expressat en el codi font. Però encara més a punt era, quan estem fent servir el depurador, vostè pot posar punts de ruptura en diferents línies de codi, el que provocarà que el depurador aturar l'execució en cadascuna d'aquestes línies perquè pugui avaluar la memòria o fins i tot canviar al seu lloc. I de nou, recordi que vostè pot crear múltiples punts d'interrupció perquè També pot reprendre l'execució, ometi sobre grans porcions de codi, i que va a fer una pausa de forma automàtica en el següent punt de ruptura. De fet, hi ha més avançat característiques del depurador, també. Però anem a haver de fer referència que a alguns vídeos posteriors amb la finalitat de burlar-se de veritat, a part de com utilitzar aquestes funcions particulars. Per ara, gràcies molt per veure. I bona sort depuració.