[? DAN ARMADARAS:?] Здравейте, Аз съм [? Dan Armadaras?]. Днес, ние ще да се търсят в отстраняване на грешки. Ние не само ще поговорим за някои техники, но и ние ще разгледаме някои от функциите, съдържаща в рамките на CS50 IDE, които позволяват лесно да трасира програма. Само един пример за нещо, което може да се обърка и това е всъщност нещо че вече сте виждали преди. В този случай, това е програма, C който приема цяло число от потребителя, тя се разделя на две, и осигурява изхода обратно към потребителя. Сега от това, което сме виждали рано в лекции, ние знаем, че това действително ще предизвика специфични видове делене проблеми когато имаме нечетни числа. Конкретно, ние просто ще изхвърлим нищо след десетичната запетая. Сега, ние знаем, че това се случва да бъде случаят. И ако ние го изпълним, ние можем да потвърдим подозренията ни, първо, чрез съставяне. И тогава, като бягане и въвеждане нечетен брой. Това не е нищо ново. Но всъщност това е Пример за бъг, който може да съществува в рамките на по-голяма програма че става по-трудно да се проследят. Въпреки, че ние знаем какво въпроса е, истинската основният проблем може да се опитва да се идентифицира специално, когато грешката се появи, идентифициране на това, което този проблем е, и след това да го отстраните. Така че предоставят тази като пример от това, което може да е нещо че ние вече знаем, но може да бъде погребан в рамките на други елементи от кода. Така че отварянето на този друг източник код на файла, като пример, това разделение проблем сега е част от по-голяма програма. Все пак може да е малко битов скалъпен, и ние може да е в състояние лесно го идентифицира, особено тъй като ние сме просто обсъждаме това. Но ние можем да разберем, че това проблем може да съществува по-голям мащаб. Ако аз обобщава и сега стартирайте го, въведете нечетно число, можем да видим, че ние не се получи точно изхода, че ние може да се очаква. В този конкретен случай, бихме могли да кажем, че сме искате да преброите всички номера от една до някаква конкретна цифра. И ние можем да видим, че ние имаме най-различни въпроси тук, ако ние сме извеждане, просто, 0 и 1, когато ние предлагаме един вход от 5. Така че ние вече знаем, че има проблем тук. Но ние не може да знае точно където този проблем не съществува в действителност. Сега един от начините, по които можем да се опитаме да се определи това е нещо, което ние сме вече са въведени, за да. Ние просто да го използвате по-голям мащаб. На линия 14, имаме това ФОРМАТ функция, което ни позволява да разпечатате на държавата на различни видове информация. И това е нещо, което ти следва да се възползва в рамките на програма да се опита да разбера какво точно е случва в различните реда код. Така че, дори и ако това не е крайния изход, че ние всъщност искат да произвеждат от тази програма, ние все още за да имам някой отстраняване на грешки отчети къде сме може да се опитват да разбера какво точно се случва вътре в нашия код. Така че в този случай, ще го направя ФОРМАТ с маркер за отстраняване на грешки. В този случай, това е просто низ отстраняване на грешки че съм в крак удар, така че тя се превръща много ясно в продукцията на моя код какво е, че искам да покажа. И изход тук числото че сме се изчислява. В този случай, бих могъл Искам да знам точно какво се случва преди и след някои специфични изчисления. Така че аз може да използва ФОРМАТ преди и след това ред код. В този случай, бих могъл дори да го направи малко по-ясно, като казва, отстраняване на грешки, преди да и отстраняване на грешки след толкова че аз самият не бъркайте с на няколко реда, които изглеждат идентични. Сега, ако ние компилирате и стартирате тази тя, като въведете номер пет отново, можем да видим, че имаме Сега изход преди и след и откриете, че не сме направили ясна разделяне или ясно като на броя че ние действително искаме да направим. Сега в този случай, това е не съвсем ясен изход. Всъщност не е ясен резултат, който искаме от тази конкретна програма. И това е, отново, по- малко скалъпен. Но, може би, едно от нещата, които бихме могли да направим, ако в спецификацията каза че искаме да разделим тази от 2 и добавете 1-- така с други думи, ние искаме да се развие след up-- бихме могли да знаем, че бихме могли да направя това нещо специално, в този случай. Сега тук ние знаем, че ние ще бъдем в състояние да добавите 1 в нашия наполовина номер. Нека да компилирате този и потвърдите, че това се държи начинът, по който искаме да. Ние можем да видим, че сега, преди да като имаме номер 5. След като имаме цифрата 3, които според нашата спецификация, е това, което искахме да направим. Но ако се вгледаме в изход тук, ние можем видим, че можем да имаме друг грешка напълно, което е че ние започваме нашата броене от 0. Сега отново, това е нещо, което сме виждали в миналото и ние можем да се определи съвсем лесно. Но в този случай, ние също имаше полза за използване на отчета за ФОРМАТ директно вътрешността на линия за да се знае точно къде тази грешка се случва. Така ФОРМАТ твърдения са много полезни в подпомагането да определите къде, Именно в изходен код, конкретна грешка се случва. И това е също важно да се осъзнае че като пишем код, можем да имаме предположения за състоянието на дадена програма. Или можем да имаме предположения за това, което е част от програмата всъщност е правилен или неправилен, когато по-късно, тъй като ние се гради върху тази програма и да го направи част от сложна и по-голяма програма че ние осъзнаваме, че някои аспекти на която всъщност е бъгав. Използването ФОРМАТ наистина може да помогне стесните и идентифициране районите на програма, която не може да се държи точно така, че ние очаква въз основа на нашите предположения. Но има и други инструменти разположение, както и, които ни позволяват да се опита да фигура къде грешка се случва и да обърне специално, какви неща се случва вътре на програмата. Така че, използвайки ФОРМАТ е много полезно, когато искаме да се идентифицират специфични области на програма, която има някакъв бъг. Но също така става досаден след известно време. В този случай, това е сравнително проста програма само с една или две променливи. И това става много лесно за нас, за да разпечатате от стойността на тези променливи в рамките на по-голям програмата. Но ние може да има различна програма, която има много променливи. И това не може да бъде доста толкова лесен за използване ФОРМАТ да се опита да се оцени това, което се случва на всеки един от тези променливи като програмата се изпълнява. Има една програма, която съществува нарича програма корекция на грешки. В този случай, тази, която ние ще използване е дебъгер GNU, или GDB, която ни позволява да се запознаят на вътрешния изработки на програмата в много по- подробен начин. Ние всъщност може да се изпълни GDB от командния ред тук, като просто напишете GDB и команда, която ние искаме да трасира. В този случай, броят. Сега в този случай, ние можем да видим, че тя ни води до бързо, че казва GDB. И ние можем действително изпълнява команди на GDB действително да започне изпълнението на програма, да го спре в определени точки, оценка на променливите и инспектира променливи, които съществува в състояние на програма в този момент, и така нататък и така нататък. Тя осигурява много енергия за нас. Но това просто така се случва че IDE CS50 също осигурява GUI или потребител интерфейс за GDB че ни позволява да направите това без да е необходимо интерфейса на командния ред каквато или изобщо дори. Начинът, по който да отворя е, като използвате бутона за отстраняване на грешки на самия връх на CS50 IDE. Сега в миналото, това, което имаме видял е, че ние използваме командата линия, за да се съберат и след това стартирате програмата. Бутонът за отстраняване на грешки прави тези две стъпки. Но тя също така ще пренесат таб дебъгер в десния която ни позволява да се запознаят с различни на свойствата на програмата тъй като се изпълнява. Ако щракнете върху отстраняване на грешки, в това случай, това ще доведе до нов раздел в конзолата прозорец на самото дъно. И вие можете да видите, че този раздел има някаква информация на самия връх. И до голяма степен можем да пренебрегнем това. Но едно от нещата, че искаме да забележите е, че да подава едно и също нещо, че ние ще получите, ако се опитаме да тече направи по програмата C в терминален прозорец. Тук можем да видим, той се движи трясък, и тя разполага с разнообразие от знамена, и е съставянето на нашия count.c файл, който е избран раздела в момента че ударих отстраняване на грешки. Така че това е много полезно, защото Сега с помощта на този бутон, за отстраняване на грешки, ние може едновременно да съставят и след това изпълнение на програмата, която ние всъщност искате да стартирате. Един от флаговете, че е важно, в този случай, всъщност сме използвали за най-дълго време но също така и просто направих някои ръка къдрене [недоловим], които е това точно тук. В трясък, той казва -ggdb3. В този случай, това, което сме казвам трясък, нашия съставител, е, че искаме да се съставят нашата програма. Но също така предоставя това, което са наречено информация символ така че всъщност има достъп компилатор до много основната информация съдържащи се в програмата. По-специално, броят на функции, които имам, имената на тези функции, променливите, видовете че тези променливи са, както и разнообразие други неща, които помагат на дебъгер изпълнява своята работа. Сега има и нещо друго това е важно да се спомене когато ние обсъждаме бягане програма по този начин. Забележете, че той има действително възпитан нов раздел в нашата конзола по дъното. Ние вече не трябва да си взаимодействат директно с терминален прозорец. Но този нов раздел е всъщност терминален прозорец. Това просто е специфична за протичане програма, която сме създали. Забележете, че в долната част, в комбинация с някои изход от звън на компилатора и GDB, които до голяма степен можем да пренебрегнем, тя всъщност показва изхода на нашата програма на самото дъно. Сега е важно да се осъзнае че това действително прозорец ще ти покажа изход от програмата си но също така може да приеме вход за тази програма, както и. Така предизвестие, което казва Моля въведете номер, която е една и съща мощност, че трябва имаше в терминален прозорец и преди. Но това вече е показано в този нов раздел. Не мога да вкара няколко. И това действително ще функция, тъй като ние очакваме ни показва нашето отстраняване на грешки, продукцията, продукцията, която може да е бъгав, както сме виждали преди. И на самото дъно, тя действително има някаква допълнителна продукция от БВП просто казвам, че тази програма е приключила. Сега като те видях в тази специално чрез серия, не е особено полезна, защото дори че имахме менюто дебъгер дойде нагоре, това е все още работеща програма. В нито един момент го направих всъщност пауза изпълнение за нас за да може да инспектира всички променливите, които се съдържат в него. Има и още нещо че ние трябва да направим, за да за да получите GDB да признае, че ние искаме за пауза на изпълнение на програмата а не само да може да се пристъпи Обикновено, колкото бихме във всеки друг случай. За да направите пауза на изпълнение, в някакъв конкретен ред, ние трябва да се създаде това, което е нарича критичната точка. И критичната точка е много лесно, създаден в този CS50 IDE, като мишката и кликнете директно на ляво на някои специфични линия номер. След като направите това, червена точка появява, което показва, че тази линия е вече критичната точка. И следващия път, че аз тичам GDB него, ще спре изпълнението по това брейк пойнт когато достигне тази линия на код. Сега това е важна нещо, за да осъзнае че това не е непременно най- случай, че всеки ред код всъщност е достъпен. Ако трябва да се създаде функция тук, за example-- невалидни F-- и просто да се направи печат линия here-- здравей world-- ако никога не съм се обадя на тази функция, то ще се окаже, че, ако задам критичната точка тук, функцията никога не ще се нарича. И поради това, този специално брейк пойнт Никога няма действително пауза изпълнение на програмата. Така че нека да кажа, че правилно се създаде критичната точка на някой ред код че действително ще бъде изпълнена. Сега в този случай, това е най- Първа линия на основната функция. Така че със сигурност ще се случи че веднага след като започне изпълнението, най-първата линия ще бъде постигнато. GDB ще направи пауза изпълнение. И тогава, аз ще бъда в състояние да взаимодействат с дебъгер. Можете да настроите няколко реда като Гранични стойности, ако искате. Можем също така да се създаде линия тук, в този сегмент на код че никога няма да се стигне. И ние също може да зададете една по-долу. Причината, че бихме искате да направите това ние ще отидат в малко по- подробно в един момент. Така че за сега, нека просто деактивирайте тези допълнителни точки за пробив така че можем да погледнем какво се случва когато имам една единствена почивка точка в програмата си. Аз направих някои промени в тази програма. Така че аз трябва да го спаси. Аз ще кликнете отстраняване на грешки, така че аз мога започне съставянето и след това изпълнение на дебъгер. Ние ще видим, че след моменти, най- линия, която ние избрахме като на почивката точка е оцветена в жълто. Можем също така да се отбележи, че в горния десен в отстраняване на грешки панел че иконата на пауза се е превърнал в една малка икона на игра. Това означава, че ние имаме пауза изпълнение, в този конкретен случай. И удря върху бутона за възпроизвеждане ще ни позволи да възобнови изпълнението при тази конкретна точка. Забележете, че има няколко други бутони на разположение за отстраняване на грешки в този панел, както добре. Стъпка над, което ми позволява да изпълни, че един ред код и стъпка към тази линия на Следващата една, която, в този случай, би означавало, че ФОРМАТ се изпълнява оператор. И след това ще направи пауза изпълнение на ред 13, като така. А има и една крачка изпълнението на функциите, които Полезно е, ако съм създал друг функции на други места в изходния код. И аз искам да се оттегли в тези функции, а не изпълнява тази функция като цяло. Но ние ще разгледаме по-по стъпка в функция в един момент. Сега забележите някои други неща, които действително съществува в рамките на този панел за отстраняване на грешки. Ние имаме този панел наречен обадете стак, което ни показва, къде точно се намираме. В този случай, ние сме вътре на основната функция. Нашият сценарий се нарича count.c. И ние се случи да бъде на ред 13, колона един, който Именно това се подчертава региона на изходния код показва, както и. Сега забелязвам, че това показва също под променливо сечение местно Всички променливи че съществува в рамките на тази функция. Важно е да се отбележи, че всички променливи ще се появи в тази локална променлива вписванията в рамките на функция, дори преди да бъдат определени. Ние можем да видим, че тук имаме променлива наречено бр, има стойност по подразбиране от 0, и е от тип Int. Сега, преди да можем действително се инициализира всички тези променливи, ние не сме задължително гарантирана, за да видите стойност 0. И в зависимост от други екзекуции че сте извършили и състоянието на паметта си, когато всъщност стартирате тази програма, може да откриете, че сте не виждам стойности от 0 и, вместо това, някои други луди номера. Но не се притеснявайте за това. Това няма да бъде от значение, докато вие всъщност се инициализира стойността. Сега в този случай, ние можем да видим, че I са извършили някои изходи. И аз, точно сега, спря екзекуция. Но в този случай, това, което Аз наистина искам да правя е да се засили вече над тази линия на код, така че мога действително заявката на потребителя за това, че инт искаме да използваме в нашата програма. Сега в този случай, когато Ударих прекрача, известие че Пауза или по-скоро на Резюмето бутон се е променило към този бутон Pause защото този код е действително изпълнение. Какво се случва точно сега е, че тя е ни чака да въведете някаква информация както можем да видим от нашата продукция текст на самото дъно. Така че точно сега, това е всъщност не спря, въпреки че, нещо се появява, да бъде, защото нищо не се случва. Но това просто така се случва, че в моя конкретен случай на ред 13, Аз чакам за приноса на потребителите. И така GDB не е в състояние да се запознаят програма, както тя се изпълнява. Сега следващия път, че да въведа някои input-- така че ще влиза, че номер 5, както сме виждали в past-- удари Върни се, и ние забележите, че непосредствено, GDB паузи и отново подчертава, на следващия ред. Но забележете, че сега, като В резултат на нашите въвеждане на стойност, актуализирахме тази стойност вътре на местните ни променливи, които Много е полезно да се знае точно какво този брой е бил в паметта. Сега мога да се позволи на тази програма, за да продължите играе до края на изпълнението й като натиснете Resume. Ние можем да видим, че много бързо прави финала на програмата изпълняващата със същата мощност, която ние имаше преди, дебъгер затваря, и сега тази програма спре напълно. I показват, че само за целите на това, което виждам се случва, когато ние действително удари Resume. Но ние всъщност ще искам да се върна в тази програма така че можем да се опитаме да трасира точно това, което се случва. Сега, аз съм с дебъгер, аз може не се нуждаят от тези за отстраняване на грешки ФОРМАТ отчети. Така че бих могъл да ги премахнете, както аз ще направя Сега, само за да се върнем към нашата опростена код че имахме преди малко. Сега, когато се запишете програмирате и да го изпълни, тя ще, отново, отидете на тази първоначална пробие точка, която имах по линия 11. И аз ще бъда в състояние да се запознаят моите променливи, както аз искам да направя. Просто така се случи, че този част не е много интересно, И знам, че аз ще съм да отпечатате тази декларация. Моля въведете число. И след това, аз знам, че аз ще съм да поиска от потребителя за това число. Така че може би, аз всъщност искате да преместите ми пробие точка малко по-надолу. Можете да премахнете точки за пробив като кликнете, отново, директно от лявата страна на този брой на линия. Това червена точка ще изчезне, което показва, че този брейк пойнт сега е отишло. Сега в този случай, изпълнение е на пауза. И така, това не е всъщност ще възобнови в този конкретен случай. Но мога да зададете пауза буква а малко по-късно. И когато аз сега възобновя код, тя ще се възобнови и да каже точката на този брейк пойнт. Отново, аз удари Resume. Не изглежда като нещо се случва. Но това е, защото ми код е в очакване на въвеждане. Аз ще въведете номер 5, удари Enter, и Сега следващата почивка точката ще бъде хит. Сега в този случай, това е линията на код че преди, ние знаехме се случи да бъде бъги. Така че нека да се оцени това, което се случва точно в този момент. Когато линията се освети, това Онлайн все още не е изпълнена. Така че в този случай, ние можем да видим че имам номер, който Имам цяло число, наречено бр, че има стойност 5. И аз отивам да бъде извършване някои математика на този номер. Ако аз прекрача, че можем забележите, че стойността за бр се е променила в съответствие с аритметиката, че всъщност сме направили. И сега, че ние сме вътре в този цикъл за или сега, че за контур Самата се освети, ние виждаме, че имаме нов променлива, наречена аз, че ще се използва в тази за цикъл. Сега не забравяйте преди това Споменахте, че понякога сте ще видим някакъв луд номера по подразбиране, преди този брой или, че е променлива всъщност инициализира. Ние можем да видим, че именно тук, в тази променлива наречена I, което не е Все още е инициализиран към момента на подчертаване. Но ние можем да видим, че има някакъв номер че ние не би действително очаква. Това е добре. Не се притеснявайте за това защото имаме всъщност не инициализира този номер, докато не прекрача тази линия и стойността I е инициализиран на стойност 1. Така че, за да се види, че това е всъщност случай, нека да прекрача. Сега можем да видим, че това Онлайн е била изпълнена. И ние сега се подчертае това ФОРМАТ линия. И сега можем да видим как нашите ценности на аз и 3 са се променили с течение на времето. Това е много полезно да се направи, в действителност, е да прекрача линии многократно. И вие можете да разберете какво всъщност се случва вътре на вашия цикъл за и какво се случва с променливи вътре на тази линия за като че изпълнението на програмата възниква една стъпка в даден момент. Сега в този момент, аз Прекрачи достатъчно само че аз сега съм в края на моята програма. Ако аз прекрача, че това ще стане всъщност престава изпълнение както видяхме в миналото. Позволете ми да се рестартира това, но отново, така че че мога да посоча нещо друго извън, както добре. В този случай, това е Сега ме питате, отново, за номер, който Ще отново влиза. Но този път, аз отивам да влиза в по-голям брой, така че за контур ще обхождане повече пъти. В този случай, аз ще съм да въведете стойност от 11. Сега отново, защото щях да зададете критичната точка по линия 15, то се случва да се подчертае, че на линия. Ние можем да видим, че нашата номер 11 е правилно представени в местните ни променливи. Засилване над това, ние можем сега гледате какво се случва с нашата стойност и докато напредваме във вътрешността на този за контур. Той получава увеличава всеки път, когато изкачат на върха на която за контур. Сега едно от нещата, които биха могли да да бъде полезно да се направи по време на изпълнение на тази програма е за мен да всъщност промяна на талвега променливи, за да видите какво се случва с моята програма. В този случай, аз мога действително кликнете два пъти върху стойността. Забележете, че тя се превръща в текстово поле. Сега мога да въведете различна ценим напълно да се види как се държи моята програма когато съм променил тази променлива. Сега в този случай, променливата аз сега съдържа стойността 10. Но програмата е все още пауза в изпълнението. Когато прекрача, виждам, че стойност аз, който съм влязъл като 10, е не по-голяма от стойността на бр, което веднага кара за контур да спре изпълнение. Сега това не е единственото причина, поради която бихте искате да модифицирате променливата на място. Вие всъщност може да искате да се опита да го променят така, че можете да продължите изпълнение на линия или, така че можете да модифицирате някаква стойност, преди да го достига някакъв специфичен набор от аритметична че сте на път да изпълни. Така че сега, че ние дори да промени стойност и като програмата се изпълнява, той е причинил на линия да се откажат преждевременно, защото, всички изведнъж, аз се случи да бъде по-голяма от стойността на бр, което означава, че за линия вече не са необходими, за да бъде изпълнена. Освен това, това се е случило, за да бъде най- случай, че сме се променили стойността на I когато линията 17 беше подчертано, която беше моментът че за изпълнение линия всъщност се оценява. Ако бях променил стойността на аз на друга линия, да речем 19, щяхме да видим различен поведение, защото линия 19 ще са изпълнени преди контура състояние се преоцени. Сега в този момент, аз съм, отново, в края на тази програма. И мога да позволим това да се пристъпи към позволи ми програма да се откажат от по-естествено. Но има няколко неща, които са важни, за да отнемат от този конкретен дискусия. Трябва да се оцени Вашите собствени предположения за това как трябва да се държи кода. Всеки път, когато си мислиш, че някои парче на код ли, че се случва да работи, че може да е червен флаг, за да отидете назад и оценка, и бъдете сигурни, че вашето предположение за как този код работи всъщност е вярно, да, как е изразена в изходния си код. Но дори и повече, за да е точка, когато ние сме с помощта на дебъгера, можете да поставите точки на прекъсване в различни реда код, което ще доведе до дебъгер пауза изпълнение на всяка една от тези линии така че можете да се оцени памет или дори да го промените на място. И пак, не забравяйте, че можете да създаване на множество точки на прекъсване, така че да също може да възобнови изпълнението, пропуснете над големи части от код, и тя автоматично ще пауза на следващото прекъсване точка. Има действително по-напреднали Гостите на дебъгер, както и. Но ние ще трябва да ви насочи до няколко последващи видеоклипове за да наистина дразни освен как да използва тези конкретни функции. За сега, благодаря ти много за гледане. И късмет отстраняване на грешки.