1 00:00:00,000 --> 00:00:02,000 [Powered by Google Translate] [Valgrind] 2 00:00:02,000 --> 00:00:05,000 [Nate Hardison, Harvard University] 3 00:00:05,000 --> 00:00:07,000 Detta är CS50, CS50.TV] 4 00:00:07,000 --> 00:00:10,000 Några av de svåraste buggar i C-program 5 00:00:10,000 --> 00:00:13,000 kommer från misskötsel av minnet. 6 00:00:13,000 --> 00:00:15,000 Det finns ett stort antal sätt att skruva upp saker, 7 00:00:15,000 --> 00:00:17,000 inklusive fördelning fel mängd minne, 8 00:00:17,000 --> 00:00:20,000 glömmer att initiera variabler, 9 00:00:20,000 --> 00:00:23,000 skriver före eller efter slutet av en buffert, 10 00:00:23,000 --> 00:00:25,000 och frigör hålla minnet flera gånger. 11 00:00:25,000 --> 00:00:28,000 Symptomen varierar från återkommande krascher 12 00:00:28,000 --> 00:00:30,000 att mystiskt överskrivna värden, 13 00:00:30,000 --> 00:00:34,000 ofta på platser och tider långt bort från den ursprungliga felet. 14 00:00:34,000 --> 00:00:37,000 Spåra den observerade problemet tillbaka till den underliggande orsaken 15 00:00:37,000 --> 00:00:39,000 kan vara en utmaning, 16 00:00:39,000 --> 00:00:42,000 men lyckligtvis finns det en bra program som heter Valgrind 17 00:00:42,000 --> 00:00:44,000 som kan göra mycket för att hjälpa. 18 00:00:44,000 --> 00:00:47,000 >> Du kör ett program under Valgrind att aktivera 19 00:00:47,000 --> 00:00:50,000 omfattande kontroller av anslagen heap minne och accesser. 20 00:00:50,000 --> 00:00:53,000 När Valgrind upptäcker ett problem, det ger dig omedelbar, 21 00:00:53,000 --> 00:00:56,000 direkt information som tillåter dig att 22 00:00:56,000 --> 00:00:58,000 lättare hitta och åtgärda problemet. 23 00:00:58,000 --> 00:01:01,000 Valgrind också rapporter om mindre dödliga minnesproblem, 24 00:01:01,000 --> 00:01:04,000 såsom minnesläckor, fördela hög minne, 25 00:01:04,000 --> 00:01:07,000 och glömmer att befria den. 26 00:01:07,000 --> 00:01:10,000 Liksom vår kompilator, klang, i vår debugger, GDB, 27 00:01:10,000 --> 00:01:14,000 Valgrind är fri programvara, och det är installerat på apparaten. 28 00:01:14,000 --> 00:01:16,000 Valgrind körs på binära körbara, 29 00:01:16,000 --> 00:01:20,000 inte din. c eller. h källfiler kod, 30 00:01:20,000 --> 00:01:23,000 så se till att du har sammanställt en up-to-date kopia av ditt program 31 00:01:23,000 --> 00:01:25,000 med klang och Make. 32 00:01:25,000 --> 00:01:28,000 Sedan kan köra ditt program enligt Valgrind vara 33 00:01:28,000 --> 00:01:32,000 så enkelt som att bara prefix standardprogrammet kommandot med ordet Valgrind, 34 00:01:32,000 --> 00:01:35,000 som startar Valgrind och kör programmet i den. 35 00:01:35,000 --> 00:01:38,000 Vid start, gör Valgrind vissa komplexa 36 00:01:38,000 --> 00:01:41,000 jiggering att konfigurera den körbara för minnet kontroller, 37 00:01:41,000 --> 00:01:44,000 så det kan ta lite för att få igång. 38 00:01:44,000 --> 00:01:48,000 Programmet kommer sedan exekvera normalt, kan det mycket långsammare, 39 00:01:48,000 --> 00:01:52,000 och när den är klar, kommer Valgrind ut en sammanfattning av dess minnesanvändning. 40 00:01:52,000 --> 00:01:58,000 Om allt går bra kommer det att se ut ungefär så här: 41 00:01:58,000 --> 00:02:01,000 I det här fallet. / Clean_program 42 00:02:01,000 --> 00:02:04,000 är sökvägen till det program jag vill köra. 43 00:02:04,000 --> 00:02:06,000 Och medan detta inte tar några argument, 44 00:02:06,000 --> 00:02:09,000 Om det gjorde jag skulle bara tack dem till slutet av kommandot som vanligt. 45 00:02:09,000 --> 00:02:12,000 Rent program är bara en dum litet program jag skapade 46 00:02:12,000 --> 00:02:15,000 som allokerar utrymme för ett block av ints i stacken, 47 00:02:15,000 --> 00:02:19,000 sätta vissa värden inne i dem, och frigör hela blocket. 48 00:02:19,000 --> 00:02:23,000 Detta är vad du fotograferar för, inga fel och inga läckor. 49 00:02:23,000 --> 00:02:27,000 >> En annan viktig variabel är det totala antalet tilldelade bytes. 50 00:02:27,000 --> 00:02:32,000 Beroende på vilket program, om dina anslag är i megabyte eller högre, 51 00:02:32,000 --> 00:02:34,000 du förmodligen gör något fel. 52 00:02:34,000 --> 00:02:37,000 Är du lagra onödan dubbletter? 53 00:02:37,000 --> 00:02:40,000 Använder du högen för lagring, när det skulle vara bättre att använda stacken? 54 00:02:40,000 --> 00:02:43,000 Så kan minnesfel vara riktigt ond. 55 00:02:43,000 --> 00:02:46,000 De mer uppenbara dem orsakar spektakulära krascher, 56 00:02:46,000 --> 00:02:49,000 men även då kan det ändå vara svårt att sätta fingret på 57 00:02:49,000 --> 00:02:51,000 vad som ledde exakt kraschen. 58 00:02:51,000 --> 00:02:54,000 Mer lömskt, ett program med en minnesfel 59 00:02:54,000 --> 00:02:56,000 kan fortfarande kompilera rent 60 00:02:56,000 --> 00:02:58,000 och kan fortfarande verkar fungera korrekt 61 00:02:58,000 --> 00:03:01,000 eftersom du lyckats få tur för det mesta. 62 00:03:01,000 --> 00:03:04,000 Efter flera "lyckade resultat", 63 00:03:04,000 --> 00:03:07,000 du kanske bara tror att en krasch är en lyckträff av datorn, 64 00:03:07,000 --> 00:03:10,000 men datorn är aldrig fel. 65 00:03:10,000 --> 00:03:13,000 >> Köra Valgrind kan hjälpa dig att spåra orsaken till synliga minnesfel 66 00:03:13,000 --> 00:03:18,000 samt hitta lurar fel du inte ens ännu känner till. 67 00:03:18,000 --> 00:03:22,000 Varje gång Valgrind upptäcker ett problem, skriver det information om vad den observerade. 68 00:03:22,000 --> 00:03:24,000 Varje objekt är ganska bryskt - 69 00:03:24,000 --> 00:03:27,000 källan raden felande instruktionen, vad frågan är, 70 00:03:27,000 --> 00:03:30,000 och lite info om de inblandade minne - 71 00:03:30,000 --> 00:03:34,000 men ofta är det tillräckligt med information för att rikta er uppmärksamhet på rätt plats. 72 00:03:34,000 --> 00:03:37,000 Här är ett exempel på Valgrind körs på en buggy program 73 00:03:37,000 --> 00:03:40,000 som gör en ogiltig läsning av heap-minne. 74 00:03:40,000 --> 00:03:49,000 Vi ser inga fel eller varningar i sammanställningen. 75 00:03:49,000 --> 00:03:53,000 Uh-oh, säger felet sammanfattningen att det finns två fel - 76 00:03:53,000 --> 00:03:56,000 två ogiltig läsningar av storlek 4 - byte, alltså. 77 00:03:56,000 --> 00:04:01,000 Både dåliga läser inträffade i huvudfunktion invalid_read.c, 78 00:04:01,000 --> 00:04:04,000 den första på ledningen 16 och den andra på ledningen 19. 79 00:04:04,000 --> 00:04:06,000 Låt oss titta på koden. 80 00:04:06,000 --> 00:04:11,000 Ser ut som det första samtalet till printf försöker läsa en int förbi i slutet av vårt minne block. 81 00:04:11,000 --> 00:04:13,000 Om vi ​​ser tillbaka på Valgrind produktion, 82 00:04:13,000 --> 00:04:16,000 Vi ser att Valgrind berättade just detta. 83 00:04:16,000 --> 00:04:19,000 Adressen vi försöker läsa startar 0 byte 84 00:04:19,000 --> 00:04:22,000 förbi änden av blocket av storlek 16 byte - 85 00:04:22,000 --> 00:04:25,000 fyra 32-bitars Ints som vi tilldelade. 86 00:04:25,000 --> 00:04:29,000 Det är, börjar den adress vi försökte läsa rätt i slutet av vår blocket, 87 00:04:29,000 --> 00:04:32,000 precis som vi ser i våra dåliga printf samtal. 88 00:04:32,000 --> 00:04:36,000 Nu kanske ogiltiga läsningar verkar inte som att stor grej, 89 00:04:36,000 --> 00:04:39,000 men om du använder dessa data för att styra flödet av ditt program - 90 00:04:39,000 --> 00:04:42,000 till exempel som en del av en if-sats eller loop - 91 00:04:42,000 --> 00:04:45,000 då saker kan tyst gå illa. 92 00:04:45,000 --> 00:04:47,000 Se hur jag kan köra invalid_read programmet 93 00:04:47,000 --> 00:04:50,000 och ingenting av det vanliga händer. 94 00:04:50,000 --> 00:04:52,000 Skrämmande, eller hur? 95 00:04:52,000 --> 00:04:56,000 >> Nu ska vi titta på några fler typer av fel som kan uppstå i din kod, 96 00:04:56,000 --> 00:04:59,000 och vi får se hur Valgrind upptäcker dem. 97 00:04:59,000 --> 00:05:01,000 Vi såg bara ett exempel på en invalid_read, 98 00:05:01,000 --> 00:05:04,000 så nu ska vi kolla en invalid_write. 99 00:05:04,000 --> 00:05:09,000 Återigen, inga fel eller varningar i sammanställningen. 100 00:05:09,000 --> 00:05:12,000 Okej, säger Valgrind att det finns två fel i detta program - 101 00:05:12,000 --> 00:05:15,000 och invalid_write och invalid_read. 102 00:05:15,000 --> 00:05:18,000 Låt oss kolla in denna kod. 103 00:05:18,000 --> 00:05:21,000 Ser ut som vi har fått en instans av den klassiska strlen plus en bugg. 104 00:05:21,000 --> 00:05:24,000 Koden inte malloc ett extra byte av utrymme 105 00:05:24,000 --> 00:05:26,000 för / 0 tecken, 106 00:05:26,000 --> 00:05:30,000 så när str kopia gick att skriva det på ssubstrlen "CS50 rocks!" 107 00:05:30,000 --> 00:05:33,000 Det skrev 1 byte förbi i slutet av vår blocket. 108 00:05:33,000 --> 00:05:36,000 Den invalid_read kommer när vi gör vår uppmaning till printf. 109 00:05:36,000 --> 00:05:40,000 Printf hamnar läsning ogiltig minne när den läser / 0 tecken 110 00:05:40,000 --> 00:05:43,000 som det ser ut i slutet av denna E-strängen är det utskrift. 111 00:05:43,000 --> 00:05:45,000 Men inget av detta flydde Valgrind. 112 00:05:45,000 --> 00:05:48,000 Vi ser att det fångade invalid_write som en del av str kopian 113 00:05:48,000 --> 00:05:51,000 på linje 11 i huvud och invalid_read är en del av printf. 114 00:05:51,000 --> 00:05:54,000 Rock på, Valgrind. 115 00:05:54,000 --> 00:05:57,000 Återigen kan detta verka inte som en stor sak. 116 00:05:57,000 --> 00:06:00,000 Vi kan köra programmet om och om igen utanför Valgrind 117 00:06:00,000 --> 00:06:03,000 och inte ser några fel symptom. 118 00:06:03,000 --> 00:06:06,000 >> Men låt oss titta på en liten variation av detta att se 119 00:06:06,000 --> 00:06:09,000 hur saker och ting kan bli riktigt illa. 120 00:06:09,000 --> 00:06:14,000 Så beviljats, vi missbrukar saker mer än bara lite i denna kod. 121 00:06:14,000 --> 00:06:17,000 Vi bara fördela utrymme på högen för två strängar 122 00:06:17,000 --> 00:06:19,000 längden CS50 stenar, 123 00:06:19,000 --> 00:06:22,000 den här gången, komma ihåg / 0 tecken. 124 00:06:22,000 --> 00:06:25,000 Men sedan vi slänga in en super-lång sträng i minnet blocket 125 00:06:25,000 --> 00:06:27,000 att S pekar på. 126 00:06:27,000 --> 00:06:30,000 Vilken effekt kommer att ha på minnet blocket att T pekar på? 127 00:06:30,000 --> 00:06:34,000 Tja, om T pekar på minnet det är precis intill S, 128 00:06:34,000 --> 00:06:37,000 kommer precis efter det, 129 00:06:37,000 --> 00:06:39,000 då vi kanske har skrivit över en del av T. 130 00:06:39,000 --> 00:06:41,000 Låt oss köra denna kod. 131 00:06:41,000 --> 00:06:43,000 Titta på vad som hände. 132 00:06:43,000 --> 00:06:47,000 Strängarna vi lagrade i våra heap blockerar både tycktes ha skrivits ut korrekt. 133 00:06:47,000 --> 00:06:49,000 Ingenting verkar fel alls. 134 00:06:49,000 --> 00:06:52,000 Men låt oss gå tillbaka till vår kod och 135 00:06:52,000 --> 00:06:55,000 kommentera ut raden där vi kopierar CS50 stenar 136 00:06:55,000 --> 00:06:59,000 in i det andra minnesblocket, utpekas av t.. 137 00:06:59,000 --> 00:07:02,000 Nu, när vi kör den här koden bör vi 138 00:07:02,000 --> 00:07:06,000 bara se innehållet i det första minnet blocket skriva ut. 139 00:07:06,000 --> 00:07:09,000 Whoa, även om vi inte Str kopia 140 00:07:09,000 --> 00:07:12,000 alla tecken i det andra högen blocket pekade en till av T, 141 00:07:12,000 --> 00:07:15,000 vi får en utskrift. 142 00:07:15,000 --> 00:07:18,000 Faktum strängen vi stoppade i vår första blocket 143 00:07:18,000 --> 00:07:21,000 överskred det första blocket och in i den andra blocket, 144 00:07:21,000 --> 00:07:23,000 gör allt verkar normalt. 145 00:07:23,000 --> 00:07:26,000 Valgrind Men berättar den sanna historien. 146 00:07:26,000 --> 00:07:28,000 Där kör vi. 147 00:07:28,000 --> 00:07:32,000 Alla dessa ogiltiga läser och skriver. 148 00:07:32,000 --> 00:07:36,000 >> Låt oss titta på ett exempel på en annan typ av fel. 149 00:07:36,000 --> 00:07:39,000 Här gör vi något ganska olyckligt. 150 00:07:39,000 --> 00:07:41,000 Vi ta plats för en int på högen, 151 00:07:41,000 --> 00:07:45,000 och vi initiera en int pekare - p - att peka på det utrymmet. 152 00:07:45,000 --> 00:07:48,000 Men medan vår pekare initieras, 153 00:07:48,000 --> 00:07:52,000 de data som det pekar på just vad skräp är den delen av högen. 154 00:07:52,000 --> 00:07:55,000 Så när vi laddar dessa uppgifter till int i, 155 00:07:55,000 --> 00:07:57,000 vi initiera tekniskt jag, 156 00:07:57,000 --> 00:08:00,000 men vi gör det med skräp data. 157 00:08:00,000 --> 00:08:03,000 Uppmaningen att hävda, vilket är en praktisk felsökning makro 158 00:08:03,000 --> 00:08:06,000 definieras i det passande namnet hävda bibliotek, 159 00:08:06,000 --> 00:08:09,000 kommer att avbryta programmet om dess prov tillstånd misslyckas. 160 00:08:09,000 --> 00:08:11,000 Det är, om i är inte 0. 161 00:08:11,000 --> 00:08:14,000 Beroende på vad som var i högen rymden pekas ut av p, 162 00:08:14,000 --> 00:08:18,000 detta program kan fungera ibland och misslyckas vid andra tillfällen. 163 00:08:18,000 --> 00:08:20,000 Om det fungerar, vi får bara tur. 164 00:08:20,000 --> 00:08:24,000 Kompilatorn kommer inte fånga detta fel, men Valgrind att vilja. 165 00:08:24,000 --> 00:08:28,000 Där ser vi felet härrör från vår användning av att skräp data. 166 00:08:28,000 --> 00:08:32,000 >> När du tilldela heap minne men inte deallokera det eller frigöra det, 167 00:08:32,000 --> 00:08:34,000 som kallas en läcka. 168 00:08:34,000 --> 00:08:37,000 För ett litet, kortlivad program som körs och omedelbart avslutas, 169 00:08:37,000 --> 00:08:39,000 läckor är ganska ofarliga, 170 00:08:39,000 --> 00:08:42,000 men för ett projekt av större storlek och / eller livslängd, 171 00:08:42,000 --> 00:08:46,000 även en liten läcka kan förvärra till något större. 172 00:08:46,000 --> 00:08:49,000 För CS50, förväntar vi att du 173 00:08:49,000 --> 00:08:51,000 ta hand om att befria hela högen minne som du fördela, 174 00:08:51,000 --> 00:08:54,000 eftersom vi vill att du ska bygga kompetens att korrekt hantera den manuella processen 175 00:08:54,000 --> 00:08:56,000 krävs av C. 176 00:08:56,000 --> 00:08:59,000 För att göra detta bör programmet ha en exakt 177 00:08:59,000 --> 00:09:03,000 en-till-en korrespondens mellan malloc och gratis samtal. 178 00:09:03,000 --> 00:09:06,000 Lyckligtvis kan Valgrind hjälpa dig med minnesläckor också. 179 00:09:06,000 --> 00:09:09,000 Här är en läckande program som heter leak.c som fördelar 180 00:09:09,000 --> 00:09:13,000 utrymme på högen, skriver till det, men inte befria den. 181 00:09:13,000 --> 00:09:16,000 Vi sammanställer det med Make och köra den under Valgrind, 182 00:09:16,000 --> 00:09:18,000 och vi ser att även vi har inget minne fel, 183 00:09:18,000 --> 00:09:20,000 Vi har en läcka. 184 00:09:20,000 --> 00:09:23,000 Det finns 16 byte definitivt förlorade, 185 00:09:23,000 --> 00:09:27,000 vilket innebär att pekaren till att minnet inte i omfattning när programmet avslutas. 186 00:09:27,000 --> 00:09:30,000 Nu ger Valgrind oss ​​inte en ton av information om läckan, 187 00:09:30,000 --> 00:09:35,000 men om vi följer den här lilla notera att det ger ner mot botten av sin rapport 188 00:09:35,000 --> 00:09:38,000 att köra med - läckage-check = full 189 00:09:38,000 --> 00:09:41,000 för att se alla detaljer om läckt minne, 190 00:09:41,000 --> 00:09:44,000 vi kommer att få mer information. 191 00:09:44,000 --> 00:09:46,000 Nu, i stacken sammanfattningen, 192 00:09:46,000 --> 00:09:50,000 Valgrind berättar om minnet som förlorades ursprungligen tilldelades. 193 00:09:50,000 --> 00:09:52,000 Precis som vi vet från att titta i källkoden, 194 00:09:52,000 --> 00:09:55,000 Valgrind informerar oss om att vi läckt minnet 195 00:09:55,000 --> 00:09:58,000 fördelas med en uppmaning till malloc på rad 8 i leak.c 196 00:09:58,000 --> 00:10:00,000 i huvudfunktionen. 197 00:10:00,000 --> 00:10:02,000 Ganska tjusig. 198 00:10:02,000 --> 00:10:04,000 >> Valgrind kategoriserar läckor med dessa termer: 199 00:10:04,000 --> 00:10:07,000 Definitivt förlorat - detta är hög allokerat minne 200 00:10:07,000 --> 00:10:10,000 som programmet inte längre har en pekare. 201 00:10:10,000 --> 00:10:14,000 Valgrind vet att du en gång hade pekaren, men har sedan förlorat kontakten med den. 202 00:10:14,000 --> 00:10:17,000 Detta minne är definitivt läckt. 203 00:10:17,000 --> 00:10:20,000 Indirekt förlorade - detta är hög allokerat minne 204 00:10:20,000 --> 00:10:24,000 som de enda pekare till den också går förlorade. 205 00:10:24,000 --> 00:10:27,000 Till exempel, om du förlorat din pekare till första noden i en länkad lista, 206 00:10:27,000 --> 00:10:30,000 då den första noden själv skulle definitivt förlorat, 207 00:10:30,000 --> 00:10:34,000 medan efterföljande noder skulle indirekt förlorad. 208 00:10:34,000 --> 00:10:37,000 Möjligen förlorade - detta är hög allokerat minne 209 00:10:37,000 --> 00:10:41,000 där Valgrind inte kan vara säker på huruvida det är en pekare eller inte. 210 00:10:41,000 --> 00:10:44,000 Fortfarande nås är hög allokerat minne 211 00:10:44,000 --> 00:10:47,000 som programmet fortfarande har en pekare vid avfart, 212 00:10:47,000 --> 00:10:50,000 vilket innebär oftast att en global variabel pekar på den. 213 00:10:50,000 --> 00:10:53,000 För att kontrollera om dessa läckor har du också omfatta möjligheten 214 00:10:53,000 --> 00:10:55,000 - Fortfarande-nås = ja 215 00:10:55,000 --> 00:10:58,000 i åkallan av Valgrind. 216 00:10:58,000 --> 00:11:01,000 >> Dessa olika ärenden kan kräva olika strategier för rengöring upp dem, 217 00:11:01,000 --> 00:11:05,000 men läckage bör undanröjas. 218 00:11:05,000 --> 00:11:08,000 Tyvärr kan fastställa läckage vara svårt att göra, 219 00:11:08,000 --> 00:11:11,000 eftersom felaktiga samtal till fri kan spränga ditt program. 220 00:11:11,000 --> 00:11:14,000 Till exempel, om vi tittar på invalid_free.c, 221 00:11:14,000 --> 00:11:18,000 Vi ser ett exempel på dåligt minne avallokering. 222 00:11:18,000 --> 00:11:21,000 Vad som borde vara ett enda samtal för att frigöra hela blocket 223 00:11:21,000 --> 00:11:24,000 minne utpekas av int_block, 224 00:11:24,000 --> 00:11:27,000 har i stället blivit ett försök att befria varje int storlek sektionen 225 00:11:27,000 --> 00:11:29,000 av minnet individuellt. 226 00:11:29,000 --> 00:11:32,000 Detta kommer att misslyckas katastrofalt. 227 00:11:32,000 --> 00:11:34,000 Boom! Vad ett fel. 228 00:11:34,000 --> 00:11:36,000 Detta är definitivt inte bra. 229 00:11:36,000 --> 00:11:39,000 Om du har fastnat med denna typ av fel, dock, och du vet inte var du ska leta, 230 00:11:39,000 --> 00:11:41,000 falla tillbaka på din nya bästa vän. 231 00:11:41,000 --> 00:11:44,000 Du gissade det - Valgrind. 232 00:11:44,000 --> 00:11:47,000 Valgrind, som alltid, vet exakt vad som händer. 233 00:11:47,000 --> 00:11:50,000 Alloc och fria räknas stämmer inte. 234 00:11:50,000 --> 00:11:52,000 Vi har 1 Alloc och 4 frigör. 235 00:11:52,000 --> 00:11:55,000 Och Valgrind berättar också om den första dåliga fri samtal - 236 00:11:55,000 --> 00:11:58,000 den som utlöste blowup - kommer från - 237 00:11:58,000 --> 00:12:00,000 linje 16. 238 00:12:00,000 --> 00:12:03,000 Som ni ser, dåliga samtal gratis är verkligen dåligt, 239 00:12:03,000 --> 00:12:05,000 så vi rekommenderar att låta ditt program läcka 240 00:12:05,000 --> 00:12:08,000 medan du arbetar på att få den funktionalitet korrekt. 241 00:12:08,000 --> 00:12:12,000 Börja leta efter läckor först efter ditt program fungerar, 242 00:12:12,000 --> 00:12:14,000 utan några andra fel. 243 00:12:14,000 --> 00:12:16,000 >> Och det är allt vi har för den här videon. 244 00:12:16,000 --> 00:12:18,000 Nu vad väntar du på? 245 00:12:18,000 --> 00:12:21,000 Gå köras Valgrind på dina program just nu. 246 00:12:21,000 --> 00:12:25,000 Mitt namn är Nate Hardison. Detta är CS50. [CS50.TV]