[? DAN ARMADARAS:?] Hei, Jeg er [? Dan Armadaras?].
I dag skal vi være ute på feilsøking.
Ikke bare skal vi snakke om noen teknikker,
men også vi kommer til å se på noen av funksjonene som finnes
innenfor CS50 IDE som tillater du enkelt kan feilsøke et program.
>> Bare ett eksempel av noe som kan gå galt
og det er faktisk noe som vi allerede har sett før.
I dette tilfelle, er dette en C-program som aksepterer et heltall fra brukeren,
deler den med to, og gir utgangen tilbake til brukeren.
Nå fra hva vi har sett tidligere i forelesninger,
vi vet at dette faktisk vil føre til bestemte typer divisjon problemer
når vi har oddetall.
>> Konkret vil vi bare kaste bort noe etter desimaltegnet.
Nå vet vi at dette skjer for å være tilfelle.
Og hvis vi kjøre den, kan vi bekrefte våre mistanker, først ved kompilering.
Og så, ved å kjøre og skrive inn et oddetall.
>> Dette er ikke noe nytt.
Men dette er faktisk en eksempel på en bug som
kan eksistere innenfor et større program som blir vanskeligere å spore opp.
Selv om vi vet hva problemet er den sanne crux av saken
kanskje prøver å identifisere spesielt der feilen oppstår,
identifisere hva som er problemet er, og deretter fikse det.
Så gi dette som et eksempel av hva som kan være noe
som vi allerede kjenner, men kan bli begravet innenfor andre elementer i koden.
>> Så åpner denne annen kilde kodefilen som et eksempel,
denne divisjonen problemet nå en del av et større program.
Fortsatt kan være litt litt contrived, og vi
kan være i stand til å enkelt identifisere det, spesielt
siden vi bare diskuterer dette.
Men vi kan finne ut at dette Problemet kan ligge på en større skala.
>> Hvis jeg kompilere dette og nå kjøre den, angir et oddetall,
Vi kan se at vi ikke får nøyaktig utgangs at vi kan ha forventet.
I dette spesielle tilfellet vi kan si at vi
ønsker å telle alle tallene fra en opp til noen bestemt nummer.
Og vi kan se at vi har en rekke problemer
her hvis vi sender ut, rett og slett, 0 og en når vi gir en inngang på fem.
>> Så vi vet allerede at det er et problem her.
Men vi kan ikke vite nøyaktig hvor dette problemet faktisk eksisterer.
Nå er en av måtene som vi kan prøve å fikse dette
er noe som vi har allerede blitt presentert for.
Vi kan bare bruke den på en større skala.
>> På linje 14, har vi dette printf funksjon,
som tillater oss å skrive ut staten av ulike typer informasjon.
Og dette er noe som du bør utnytte i programmet
for å prøve å finne ut nøyaktig hva som er skjer på ulike linjer med kode.
Så selv om dette ikke er endelige resultatet at vi faktisk
ønsker å produsere ut av dette programmet, vi fortsatt
kanskje har noen debug setninger der vi
kan prøve å finne ut nøyaktig hva som skjer inne i vår kode.
>> Så i dette tilfellet, vil jeg printf med debug tag.
I dette tilfelle, er denne bare en debug streng
at jeg er opp-putting slik at det blir veldig klart i utgangen av min kode
hva det er at jeg ønsker å vise.
Og utgang her antall som vi har beregnet.
>> I dette tilfellet, kan jeg ønsker å vite nøyaktig
hva som skjer før og etter noen spesifikk beregning.
Så jeg kan bruke en printf før og etter at kodelinje.
I dette tilfellet kunne jeg selv gjøre det litt mer klart
ved å si debug før og feilsøke etter så
at jeg ikke forvirre meg selv med flere linjer som ser identiske.
>> Nå hvis vi rekompilere dette og kjøre det, angir et nummer som fem igjen,
Vi kan se at vi har nå produksjonen før og etter
og finner ut at vi ikke har gjort en klar divisjon eller klart ha av antallet
at vi faktisk ønsker å gjøre.
Nå i dette tilfelle, er denne ikke egentlig en klar utgang.
Det er egentlig ikke et klart utfall som vi ønsker ut av denne spesielle program.
>> Og dette er, igjen, en litt contrived.
Men, kanskje en av de tingene som vi kunne gjøre hvis spesifikasjonen sa
at vi ønsker å dele dette med 2 og legge 1-- så med andre ord,
vi ønsker å runde opp-- deretter vi kunne vite at vi kunne
gjøre det bestemt ting, i dette tilfellet.
Nå her vi vet at vi vil være legge en til vår halvert antall.
>> La oss rekompilere dette og bekrefter at dette
oppfører seg slik som vi vil.
Vi kan se at nå før ha, har vi nummer fem.
Etter å ha, har vi nummer tre, som i henhold til vår spesifikasjonen,
er hva vi ønsket å gjøre.
Men hvis vi ser på utgang her, kan vi
se at vi kan ha en annen bug helt, noe som er
at vi starter vår teller fra 0.
>> Nå igjen, dette er noe som vi har sett i det siste
og vi kan fikse ganske lett.
Men i dette tilfellet, vi også hadde nytte
for å bruke printf uttalelse direkte på innsiden av for loop
å vite nøyaktig hvor at feilen var oppstått.
Så printf uttalelser er svært nyttig i å hjelpe
du bestemme hvor, nettopp i kildekoden,
en spesifikk feil oppstår.
>> Og det er også viktig å innse det, som vi skriver kode,
vi kan ha forutsetninger om tilstanden i et program.
Eller vi kan ha forutsetninger om hvilken del av programmet
er faktisk riktig eller feil når senere som vi bygger videre på det programmet
og gjøre det en del av en komplekse og større program
at vi innser at noen aspekter av det er faktisk buggy.
>> Ved hjelp av printf virkelig kan hjelpe innskrenke og identifisere
regionene i et program som ikke kan skal oppføre seg akkurat slik at vi
forventer, basert på våre antagelser.
Men det er andre verktøy tilgjengelig, samt,
som tillater oss å prøve å finne ut hvor en feil er oppstått
Og også, spesifikt, hva ting skjer inne i programmet.
>> Så bruker printf er veldig nyttig når vi ønsker
for å identifisere spesifikke områder av et program som har noen bug.
Men det blir også kjedelig etter en stund.
I dette tilfelle, er dette en relativt enkelt program
med bare én eller to variabler.
Og blir det veldig enkelt for oss å skrive ut verdien av disse variablene
i sammenheng med den større program.
>> Men vi kan ha en annen program som har mange variabler.
Og det er kanskje ikke helt så lett å bruke printf
å forsøke å vurdere hva som skjer til hver og en av disse variablene
som programmet utfører.
Det er et program som eksisterer kalles en debugger program.
I dette tilfellet, som vi vil bruk er GNU debugger, eller GDB,
som tillater oss å inspisere den interne arbeidet i et program i en mye mer
detaljert måte.
>> Vi kan faktisk kjøre GDB fra kommandolinjen
her ved å skrive GDB og kommando som vi ønsker å feilsøke.
I dette tilfelle teller.
Nå i dette tilfellet, kan vi se at det bringer oss til en melding som sier GDB.
Og vi kan faktisk utføre kommandoer til GDB
å faktisk begynne utførelsen av program, stoppe det på enkelte punkter,
evaluere variablene og inspisere de variablene som
finnes i programtilstand på det aktuelle tidspunktet,
og så videre og så videre.
Det gir mye makt til oss.
>> Men det bare så skjer at CS50 IDE også
gir et GUI eller en bruker grensesnitt for GDB som
tillater oss å gjøre dette uten å måtte kommandolinjegrensesnittet hodet
eller i det hele tatt enda.
Den måten jeg kan få tilgang til er ved hjelp av debug-knappen
på toppen av CS50 IDE.
Nå i det siste, hva vi har sett er at vi bruker kommandoen
linje for å kompilere og kjøre et program.
>> Debug knapp gjør begge disse trinnene.
Men det vil også få opp debugger fanen lengst til høyre
som tillater oss å inspisere en rekke av egenskapene til det program
som det blir utført.
Hvis jeg klikker debug, i dette tilfelle, vil det gi opp
en ny fane i konsollen vindu helt nederst.
>> Og du kan se at denne kategorien har litt informasjon på toppen.
Og vi kan i stor grad ignorere dette.
Men en av de tingene at vi ønsker å legge merke til
er at det utganger det samme som vi
ville fått hvis vi prøvde å kjøre gjøre på C-program i terminalvinduet.
>> Her kan vi se den kjører klang, og den har en rekke flagg,
og det er å samle vår count.c fil, som var den valgte kategorien på tiden
at jeg traff debug.
Så dette er veldig nyttig fordi nå bruker denne debug-knappen,
kan vi samtidig kompilere og deretter kjøre programmet at vi faktisk
vil kjøre.
>> En av de flagg som er viktig, i dette tilfellet
vi har faktisk vært å bruke for lengst
men også bare gjorde noen hånd vinke [uhørbart], som
er dette en rett her.
I klang, sier -ggdb3.
I dette tilfellet, det vi forteller klang, vår kompilator,
er at vi ønsker å kompilere programmet vårt.
Men også gi hva er kalt symbolinformasjon
slik at kompilatoren faktisk har tilgang til mye av den underliggende informasjon
inneholdes i programmet.
>> Mer spesielt er antallet av funksjoner som jeg har,
navnene på disse funksjoner, variablene, hvilke typer
at disse variabler er, og en rekke av andre ting som hjelper debugger
utføre sin operasjon.
Nå er det noe annet det er viktig å nevne
når vi diskuterer løping et program på denne måten.
>> Legg merke til at det har faktisk brakt opp en ny fane i vår konsoll
langs bunnen.
Vi trenger ikke lenger å samhandle direkte med terminalvinduet.
Men denne nye kategorien er faktisk et terminalvindu.
Det er bare bestemt til driften program som vi har skapt.
>> Legg merke til at på bunnen, i kombinasjon med noen utgang
av clang kompilatoren og GDB, som vi kan i stor grad ignorere,
det faktisk viser resultatet av programmet vårt helt nederst.
Nå er det viktig å innse at dette vinduet faktisk
vil vise deg utgang fra programmet
men også kan akseptere innspill for det program, samt.
>> Så varsel som sier Skriv inn et tall,
som er den samme produksjonen som vi hadde hadde i terminalvinduet før.
Men det er nå vist i denne nye kategorien.
Jeg kan legge inn et nummer.
Og det vil faktisk funksjon som vi forventer
viser oss våre feilsøke, utgang, utgang som kan være buggy,
som vi har sett før.
Og helt nederst, det faktisk har noen ekstra utgang
fra BNP sier bare at dette programmet er fullført.
>> Nå som du så i denne Spesielt kjøre gjennom,
Det var ikke særlig nyttig fordi selv
om vi hadde debugger menyen kommer opp, dette var likevel et kjørende program.
Ikke på noe punkt gjorde det faktisk stanse henrettelsen for oss
for å kunne inspisere hele variablene som finnes.
Det er noe annet at vi må gjøre for
å få GDB å erkjenne at vi ønsker for å stanse gjennomføringen av programmet
og ikke bare tillate den å gå videre normalt som vi ville i alle andre tilfeller.
>> For å stanse henrettelsen, på noen bestemt linje,
vi trenger for å lage hva som er kalles et avbruddspunkt.
Og en pause punkt er veldig enkelt laget i denne CS50 IDE ved å ta musen
og klikke direkte til venstre av noen bestemt linjenummer.
Når jeg gjør det, en rød prikk vises, noe som indikerer
at den linjen er nå en pause punkt.
>> Og neste gang jeg kjører GDB, det vil stoppe henrettelsen på det pause punkt
når den når den kodelinje.
Nå er dette en viktig ting å innse
at det ikke nødvendigvis Ved at hver linje med kode
er faktisk tilgjengelig.
Hvis jeg skulle lage en funksjon her oppe, for example-- ugyldig f--
og bare gjøre en utskrift linje her-- hallo world-- om jeg aldri kalle denne funksjonen,
vil det være slik at, hvis jeg setter en pause poeng her,
funksjonen vil aldri bli kalt.
Og derfor denne Særlig break point
vil aldri stoppe gjennomføring av programmet.
>> Så la oss si at jeg riktig opprette en pause punkt på noen linje med kode
som faktisk vil bli henrettet.
Nå i dette tilfellet, er dette første linje i hovedfunksjon.
Så det vil sikkert være tilfelle at så snart jeg begynner gjennomføring,
den aller første linjen vil bli nådd.
GDB vil stanse henrettelsen.
Og da vil jeg være i stand til å samhandle med debugger.
>> Du kan stille inn flere linjer som breakpoints, hvis du ønsker.
Vi kan også lage en linje opp her i dette segmentet av kode
som aldri vil bli nådd.
Og vi kan også opprette en nærmere nedenfor.
Grunnen til at vi ville ønsker å gjøre dette vi vil
gå inn i en litt mer detalj i bare et øyeblikk.
Så for nå, la meg bare deaktivere disse ekstra brytepunkter
slik at vi kan se på hva som skjer når jeg har en eneste pause
punkt i mitt program.
Jeg har gjort noen endringer i dette programmet.
Så jeg trenger å lagre det.
Jeg vil klikke debug slik at jeg kan begynne utarbeidelse og deretter
gjennomføring av debugger.
>> Vi vil se at etter øyeblikkene, de linje som vi valgt som pause
punkt er markert med gult.
Vi kan også legge merke til at i øverst til høyre i debug panel
at pausen ikonet har slått inn litt lek ikon.
Dette betyr at vi har pause utførelse, i dette spesielle tilfelle.
Og trykket på play-knappen vil tillate oss å gjenoppta kjøring
på det bestemt punkt.
>> Legg merke til at det er et par andre knappene som er tilgjengelige i denne debug panel,
også.
Gå over, som tillater meg å utføre som en linje med kode
og gå over til den linje til neste, som i dette tilfellet
ville bety at printf setningen utføres.
Og det vil deretter pause kjøring på linje 13, som så.
>> Og det er også et skritt i funksjon, hvilken
er nyttig hvis jeg har skapt andre funksjoner andre steder i kildekoden.
Og jeg ønsker å gå inn disse funksjonene i stedet
utføre som fungerer som en helhet.
Men vi vil se mer på trinnet i funksjon i løpet av et øyeblikk.
Nå merke noen andre ting som faktisk eksisterer innenfor denne debug panel.
>> Vi har dette panelet kalles kaller stack, som viser oss
hvor vi er.
I dette tilfellet, er vi inne til hovedfunksjonen.
Vår script kalles count.c.
Og vi måtte være på linje 13, en kolonne, hvilken
er nettopp hva den markerte regionen av kildekoden indikerer at, i tillegg.
>> Nå merker at dette viser også under den lokale variable delen
alle variablene som eksisterer innenfor denne funksjonen.
Det er viktig å merke seg at alle variablene
vises i denne lokal variabel seksjon innenfor en funksjon,
til og med før de er definert.
Vi ser her at vi har en variabel kalt num, har en standardverdi på 0,
og det er av typen int.
>> Nå før vi faktisk initial alle disse variablene,
vi er ikke nødvendigvis garantert å se en verdi på 0.
Og avhengig av andre henrettelser at du har utført
og staten hukommelsen når du faktisk kjøre dette programmet,
du kan finne det du ikke ser verdiene av 0
og, istedenfor, noen andre sprø tall.
>> Men ikke bekymre deg om det.
Det kommer ikke til å være relevant til du faktisk initial verdien.
Nå i dette tilfellet, kan vi se at Jeg har gjort noen utganger.
Og jeg, akkurat nå, stanset henrettelsen.
Men i dette tilfelle, hva Jeg ønsker virkelig å gjøre
er å nå gå over denne linjen av koden slik at jeg faktisk kan
spørre brukeren for at int som vi ønsker å bruke i vårt program.
>> Nå i dette tilfellet, når Jeg traff gå over, varsel
at Pause eller snarere Resume knappen er endret til dette Pause-knappen
fordi denne kode er faktisk utfører.
Hva er det som skjer akkurat nå er at det er
venter på oss for å legge inn litt informasjon som vi kan se av produksjonen vår tekst
helt nederst.
>> Så akkurat nå, er dette faktisk ikke stanset,
selv om det, liksom, vises å være fordi ingenting skjer.
Men det har seg slik at i min spesifikke saken på linje 13,
Jeg venter på brukerundersøkelser.
Og så GDB er ikke i stand til å inspisere et program som det er i gang.
>> Nå neste gang jeg skriver noe input-- så jeg skal gå inn som nummer fem,
som vi har sett i past-- hit Return, og vi
Legg merke til at med en gang, GDB pauser og, igjen, understreker neste linje.
Men legg merke til at nå, som en Resultatet av vår legge inn en verdi,
Vi har oppdatert at verdien inne av våre lokale variabler, som
er svært nyttig å vite nøyaktig hva det tallet var i minnet.
>> Nå kan jeg tillate dette programmet til å fortsette spille til slutten av sin utførelse
ved å treffe Resume.
Vi kan se at svært raskt gjør programmet ferdig utførende
med den samme produksjonen som vi hatt før, debugger lukkes,
og nå dette programmet har stoppet helt.
>> I viser at bare for formålene med å se hva
skjer når vi faktisk treffer Resume.
Men vi faktisk kommer til å ønsker å gå tilbake til dette programmet
slik at vi kan prøve å feilsøke nøyaktig hva som skjer.
Nå som jeg bruker debugger, kan jeg ikke trenger disse debug printf uttalelser.
>> Så jeg kan flytte dem som jeg vil gjøre nå bare å gå tilbake til vår enklere kode
at vi hadde et øyeblikk siden.
Nå når jeg lagrer programmere og kjøre den,
det vil, igjen, gå til den innledende bryte punktet at jeg hadde på linje 11.
Og jeg skal være i stand til å inspisere mine variabler som jeg ønsker å gjøre.
>> Det bare så skjer at denne del er ikke veldig interessant,
Og jeg vet at jeg kommer å skrive ut denne uttalelsen.
Vennligst skriv inn et nummer.
Og så vet jeg at jeg kommer å spørre brukeren om at heltall.
Så kanskje jeg faktisk ønsker å flytte min bryte punkt litt lenger ned.
>> Du kan fjerne break poeng ved å klikke igjen, direkte
til venstre for denne linjen nummer.
Det røde prikken forsvinner, indikerer at det knekkpunktet er nå borte.
Nå i dette tilfellet henrettelsen er midlertidig stoppet.
Og så det er ikke faktisk kommer til å fortsette i det aktuelle tilfellet.
Men jeg kan sette en pause peke litt senere.
>> Og når jeg nå gjenoppta min kode, vil den fortsette og fortelle
poenget med at knekkpunktet.
Igjen, jeg traff Resume.
Ser ikke ut som noe som skjer.
Men det er fordi min kode venter på inngangen.
Jeg vil legge inn et nummer fem, trykk Enter, og nå neste break point vil bli rammet.
>> Nå i dette tilfelle denne er linjen med kode
det, før vi visste tilfeldigvis buggy.
Så la oss vurdere hva som skjer på dette spesielle tidspunktet.
Når en linje er uthevet, dette linje har ennå ikke blitt utført.
Så i dette tilfellet, kan vi se at jeg har et nummer, som
Jeg har et heltall kalles num som har en verdi 5.
Og jeg kommer til å være utøvende litt matematikk på dette nummeret.
>> Hvis jeg gå over det, kan vi Legg merke til at verdien for num
er endret i henhold til aritmetikk at vi faktisk har gjort.
Og nå som vi er innsiden av denne for loop
eller nå som for loop selv er markert,
vi ser at vi har en ny variabel kalt jeg at
kommer til å bli brukt i den for loop.
>> Nå husker før at jeg nevnt at noen ganger du er
kommer til å se en slags gal numre som standard før det nummeret
eller at variabelen er faktisk initialisert.
Vi kan se at nettopp her i denne variabelen
heter jeg, som ikke har ennå ikke blitt initialisert
ved å fremheve.
Men vi kan se at det har noen tall at vi ikke ville faktisk forvente.
>> Det er greit.
Ikke bry deg om det fordi vi har faktisk ikke
initialisert det nummeret før jeg gå over denne linjen og verdien
Jeg har blitt initialisert til verdien 1.
Så for å se at det er faktisk tilfelle, la oss gå over.
Vi kan nå se at det linjen har blitt henrettet.
Og vi er nå fremhever dette printf linje.
>> Og vi kan nå se hvordan våre verdier av jeg og 3 har endret seg over tid.
Dette er svært nyttig å gjøre, faktisk, er å gå over linjene flere ganger.
Og du kan finne hva som faktisk skjer innsiden av for loop
og hva som skjer med variabler inne på at for loop
som at programmet kjøres oppstår ett skritt om gangen.
>> Nå på dette punktet, jeg tråkket over akkurat nok
at jeg nå er på slutten av mitt program.
Hvis jeg gå over det, vil det faktisk opphøre henrettelse
som vi har sett i det siste.
La meg starte dette, enda en gang, så at jeg kan peke noe annet ut,
også.
>> I dette tilfelle er det nå spør meg igjen,
for et tall, som Jeg vil, igjen, gå inn.
Men denne gangen kommer jeg til å gå inn i et større antall, slik at for loop
vil reagere flere ganger.
I dette tilfellet, jeg kommer å angi en verdi av 11.
>> Nå igjen fordi jeg hadde satt en pause punkt på linje 15,
det kommer til å markere den linjen.
Vi kan se at vår nummer 11 er riktig
representert i våre lokale variabler.
Tråkke over at vi kan nå se hva som skjer til vår verdi i
når vi fortsetter på innsiden av denne for sløyfen.
Det blir økes hver gang vi når toppen av det for loop.
>> Nå er en av de tingene som kanskje være nyttig å gjøre under utførelse
med dette programmet er for meg å faktisk endre variabler midtstrøms å se
hva som skjer med mitt program.
I dette tilfellet kan jeg faktisk Dobbeltklikk verdien.
Legg merke til at det blir et tekstfelt.
>> Nå kan jeg skrive annerledes verds helt
for å se hvordan mitt program oppfører seg når jeg har endret den variabelen.
Nå i dette tilfellet, den variable jeg nå inneholder verdien 10.
Men programmet er fremdeles pauset i kjøring.
Når jeg går over, jeg ser at verdi i, som jeg skrev som 10,
ikke er større enn verdien av num, som umiddelbart fører til at for loop
å stoppe gjennomføring.
>> Nå det er ikke den eneste Grunnen til at du ville
ønsker å endre den variable på plass.
Du kan faktisk ønsker for å prøve å endre det slik
at du kan fortsette utførelse av en løkke
eller slik at du kan endre noen verdi før det
når noen bestemt sett av aritmetiske at du er i ferd med å utføre.
>> Så nå som vi faktisk endre Verdien av jeg så programmet ble utførende,
det forårsaket for loop å slutte tidlig på grunn, plutselig, jeg
skjedde til å være større enn verdien av num, noe som betyr at det for loop
ikke lenger nødvendig å bli henrettet.
Videre skjedde det å være Ved at vi endret verdien av jeg
når linjen 17 ble fremhevet, som var poenget i tid
at for loop kjøring ble faktisk blir evaluert.
>> Hvis jeg hadde endret verdien av jeg på en annen linje, sier 19,
vi ville ha sett annerledes atferd fordi linje 19 ville
har utført før løkken Tilstanden ble revurdert.
Nå på dette punktet, er jeg, igjen, ved slutten av dette programmet.
Og jeg kan la dette fortsette til tillate mitt program til å avslutte naturlig.
Men det er et par ting som er viktig å ta bort
fra denne diskusjonen.
Du må vurdere dine egne forutsetninger
om hvordan koden skal oppføre seg.
Hver gang du tror at noen stykke av koden du vet skjer til å arbeide,
som kan være et rødt flagg for å gå tilbake og vurdere, og sørg
at forutsetningen om hvordan koden fungerer
er faktisk sant til hvordan det er uttrykt i kildekoden.
>> Men enda mer til poenget var, når vi bruker debugger,
du kan sette stoppunkter på ulike linjer med kode,
noe som vil føre til at debugger til pause utførelse ved hver av disse linjer
slik at du kan evaluere minne eller endre det på plass.
Og igjen, husk at du kan opprette flere stoppunkter, slik at du
kan også gjenoppta kjøring, hopp over store deler av koden,
og det vil automatisk pause ved neste pause punkt.
>> Det er faktisk mer avansert funksjonene i debugger, så vel.
Men vi må henvise deg til noen påfølgende videoer
for å virkelig erte hverandre hvordan å bruke de bestemte funksjoner.
For nå, takk veldig mye for å se på.
Og lykke debugging.