[Powered by Google Translate] [Tydzień 5] [David J. Malan - Harvard University] [To jest CS50. - CS50.TV] To CS50, Tydzień 5. Dziś i ten tydzień, przedstawiamy trochę świata forensics w kontekście problemu Set 4. Dzisiaj będzie skrócona wykład bo jest szczególnym wydarzeniem w tutaj później. Będziemy więc zerknąć i drażnić zarówno uczniów jak i rodziców już dziś niektóre z rzeczy, które są na horyzoncie. Wśród nich, od poniedziałku, będzie jeszcze kilka kolegów. EDX, Harvard i najnowsza inicjatywa MIT OpenCourseWare i więcej, jest uruchomienie na terenie kampusu Uniwersytetu Harvarda w poniedziałek, co oznacza pochodzić poniedziałek trzeba będzie, jak z ostatniego liczenia, 86.000 dodatkowych kolegów Kto będzie wraz z wykładów CS50 i sekcje i solucje i zestawy problem. I jako część tego, staniecie się członkami klasy inauguracyjnym CS50 i teraz CS50x. W ramach tego teraz, uświadomić sobie, że będzie kilka upsides również. Aby przygotować się do tego, do ogromnej liczby uczniów, wystarczy powiedzieć, że nawet jeśli mamy 108 TFS i CAS, nie dość najlepszy stosunek nauczyciel-uczeń jest raz trafiliśmy 80.000 studentów. Nie jedziemy do klasyfikacji tak wiele problemu ustawia ręcznie, tak przedstawił w tym tygodniu w zestawie problem zostanie CS50 Check, który ma być narzędziem wiersza polecenia wewnątrz urządzenia że dostaniesz po zaktualizowaniu go później w ten weekend. Będzie można uruchomić polecenie, check50, na własnym PSET, a otrzymasz natychmiastową informację zwrotną, czy program jest poprawny lub według różnych specyfikacji projektowych, które podajemy. Więcej na ten temat w opisie zestaw problemów. W CS50x koledzy będą korzystać to za dobrze. Set 4 Problem jest o kryminalistyce, i to pset naprawdę inspirowane przez niektóre rzeczy rzeczywistych przy czym, gdy byłem na studiach I internowany na chwilę z adwokatem Middlesex County dzielnicy biuro robi ekspertyzy, ich główny badacz kryminalistycznych. Co ta wynosiła, jak myślę, już wspomniałem kilka tygodni przeszłości, jest policja lub inne państwowe masowe przychodził, oni zostawić rzeczy jak dyski twarde i płyty CD i dyskietki i tym podobnych, a następnie celem Urzędu kryminalistycznych było ustalenie czy istnieje lub nie był dowód pewnego rodzaju. To było specjalne Dochodzenia, więc było umysłowych przestępczości. To było bardziej niepokojący rodzaj zbrodni, wszystko obejmujący jakiś mediów cyfrowych. Okazuje się, że nie, że wiele osób, napisać e-maila o treści: "Zrobiłem to". Tak często, te kryminalistyczne wyszukiwania nie pojawił się aż tak dużo owoców, ale czasem ludzie będą pisać takie maile. Więc czasami, wysiłki zostały nagrodzone. Ale żeby doprowadzić do tego kryminalistycznych PSET, będziemy wprowadzenie w pset4 trochę grafiką. Prawdopodobnie wziąć te rzeczy za pewnik - JPEG, GIF, i jak - w tych dniach. Ale jeśli naprawdę myślisz o tym, obraz, podobnie jak twarz Roba, może być modelowana, jak w sekwencji lub punktów pikseli. W przypadku powierzchni Roba, nie wszystkie rodzaje kolorów i zaczęliśmy zobaczyć poszczególne punkty, inaczej znany jako pikseli, raz zaczęliśmy, aby powiększyć Ale jeśli uprościć świat trochę i po prostu powiedzieć, że to o to Rob w czerni i bieli, do reprezentowania czarne i białe, możemy po prostu użyć binarny. A jeśli będziemy używać binarnych, 1 lub 0, możemy wyrazić ten sam obraz z uśmiechem na twarzy Roba z tego wzorca bitów. 11000011 reprezentuje biały, biały, czarny, czarny, czarny, czarny, biały, biały. I tak to nie jest to ogromny skok jest wtedy zacząć mówić o kolorowych fotografiach rzeczy, które chcesz zobaczyć na Facebook lub wziąć z aparatu cyfrowego. Ale na pewno, jeśli chodzi o kolory, potrzebujesz więcej bitów. I dość powszechne w świecie fotografii jest używać nie 1-bitowy kolor, jak to sugeruje, ale 24-bitowy kolor, w którym rzeczywiście się miliony kolorów. Tak więc, jak w przypadku, gdy w powiększeniu na oko Roba, to było dowolną liczbę milionów różnych kolorowych możliwości. Więc będziemy wprowadzać to w secie Problem 4, jak również w instrukcji który będzie dziś o 3:30, zamiast zwykłej 2:30 bo wykładu piątkowego tutaj. Ale wideo online będzie jak zwykle jutro. Będziemy także wprowadzenie do innego formatu pliku. To jest celowo ma wyglądać zastraszenia w pierwszym, ale jest to tylko część dokumentacji struct C. Okazuje się, że rok temu Microsoft pomógł spopularyzować ten format nazywany bitmap format, bmp, i to było super proste, kolorowe format pliku graficznego , który był używany przez jakiś czas, a czasami jeszcze do tapet na pulpitach. Jeśli uważasz, że powrót do systemu Windows XP i wzgórz i błękitne niebo, to było zazwyczaj obraz bmp lub bitmap. Bitmapy są zabawne dla nas, bo mają trochę więcej złożoności. To nie jest takie proste, jak się to siatki 0s i 1s. Zamiast tego masz takie rzeczy jak nagłówek na początku pliku. Więc innymi słowy, wewnątrz pliku. Bmp jest cała masa 0s i 1s, ale jest kilka dodatkowych 0s i 1s tam. I okazuje się, że to, co zapewne za pewnik od lat - formaty plików, takie jak. doc lub. xls lub. mp3, mp4,. cokolwiek formaty plików że jesteś zaznajomiony z - co to w ogóle znaczy być format pliku, , ponieważ na końcu dnia wszystkie pliki mają tylko używamy 0s i 1S. A może te 0s i 1s reprezentować ABC ASCII lub podobnego, a na końcu dnia, to jest jeszcze tylko 0s i 1S. Więc ludzie, tylko sporadycznie decydują się stworzyć nowy format pliku gdzie standaryzacja co wzorce bitów rzeczywiście myśli. I w tym przypadku tutaj, ludzie, którzy zaprojektowany format pliku bitmapy powiedział, że na pierwszy bajt w pliku mapy bitowej, jak oznaczone offsetowych 0 tam, tam będzie trochę tajemniczo nazwana zmienna nazwana bfType, które po prostu oznacza bitmapy typu pliku, jaki typ plików graficznych jest to. Można wywnioskować, może z drugiego rzędu, że przesunięcie 2, nr 2, bajt ma wzorzec 0s i 1s, który reprezentuje co? Rozmiar czegoś. I idzie tam. Więc w secie Problem 4, będziesz szedł przez niektóre z tych rzeczy. Nie skończy się dbać o wszystkich z nich. Zauważmy jednak, że zaczyna się ciekawie wokół bajcie 54: rgbtBlue, Zielony i Czerwony. Jeśli kiedykolwiek słyszał skrót RGB - czerwony, zielony, niebieski - to jest odniesienie do bo okazuje się, można malować wszystkie kolory tęczy z niektórych kombinacji czerwony i niebieski i zielony. A w rzeczywistości, rodzice w pokoju może przypomnieć niektóre z najwcześniejszych projektorów. Te dni, wystarczy zobaczyć jeden jasne światło wychodzące z obiektywu, ale już w dzień trzeba było czerwone, niebieskie soczewki obiektywu, a zielona soczewka, i razem ukierunkowane na ekranie i tworzy barwny obraz. I dość często, gimnazja i szkoły średnie będą mieć te soczewki nigdy tak lekko krzywo, więc były rodzaju widzenie podwójne lub potrójne obrazy. Ale to był pomysł. Trzeba było czerwone i zielone i niebieskie światło, malowanie obrazu. I że sama zasada jest stosowana w komputerach. Tak więc niektóre z wyzwań dla Ciebie w ówczesnych problem Set 4 będą kilka rzeczy. Jednym z nich jest rzeczywiście zmienić rozmiar obrazu, do podjęcia w strukturze 0s i 1s, dowiedzieć się, które kawałki 0s i 1s reprezentuje to co w strukturze jak ten, , a następnie dowiedzieć się, jak powielanie pikseli - The Reds, blues, Zieloni - wewnątrz tak, że gdy obraz wygląda początkowo Może to wyglądać tak, a nie po. Wśród innych wyzwań zbyt będzie, że będziesz wręczył kryminalistycznych obraz o rzeczywistej pliku z aparatu cyfrowego. I na tym aparacie, kiedyś były cała masa zdjęć. Problem jest, że przypadkowo usunięte lub miał obraz uszkodzony jakoś. Złe rzeczy się aparatami cyfrowymi. I tak szybko kopiowane wszystkie 0s i 1s off tej karty dla Ciebie, zapisane je wszystkie w jeden duży plik, a potem oddajemy je do Ciebie w Problem Set 4 tak, że można napisać program w języku C, z którym w celu odzyskania tych wszystkich plików JPEG, idealnie. I okazuje się, że pliki JPEG, choć są one nieco złożonego formacie pliku - są o wiele bardziej złożone, niż się to uśmiechnięta twarz tu - Okazuje się, że każdy JPEG rozpoczyna się tymi samymi wzorami 0s i 1s. Więc korzystając ostatecznie, pętla lub pętli for lub podobne, można iterować wszystkie 0s i 1s w tym kryminalistycznych obrazu, i za każdym razem pojawi się specjalny wzór, który jest zdefiniowany w specyfikacji zestaw problemów, można założyć o to, z bardzo wysokim prawdopodobieństwem, początek JPEG. I jak najszybciej znaleźć tego samego wzorca pewną liczbę bajtów lub kilobajtach lub megabajtach później, można przypuszczać, o to sekundy JPEG, zdjęcie wziąłem po pierwszej. Pozwól mi przestać czytać ten pierwszy plik, zacząć pisać ten nowy, i wyjście z programu do pset4 będzie aż 50 JPEG. A jeśli to nie jest 50 plików JPEG, masz trochę pętli. Jeśli masz nieskończoną liczbę JPEG, masz nieskończoną pętlę. Więc to też będzie dość częsty przypadek. Więc to, co jest na horyzoncie. Quiz 0 za nami, zrealizować za mojego maila, że ​​zawsze są ludzie, którzy są zarówno szczęśliwi, rodzaj neutralnej i smutne okolice quizu 0 czasu. I proszę do mnie dotrzeć, szef TF Zamyla, własne TF, lub w jednym z urzędów, że wiesz, czy chcesz, aby przedyskutować jak poszło. Tak więc, aby zaimponować rodzicom tutaj w pokoju, co jest CS50 biblioteka? [Śmiech] Dobra robota. Co CS50 biblioteka? Tak. >> [Uczeń] To pre-napisany zestaw kodu [niesłyszalne] Dobra, dobra. To jest pre-napisany zestaw kodu, że personel napisał, oferujemy Państwu, , która zapewnia pewne wspólne funkcje, Rzeczy jak załatwić mi łańcuch, żebym int - wszystkie funkcje, które są tutaj wymienione. Od teraz zaczynamy naprawdę wziąć te kółka off. Zamierzamy rozpocząć zabrać ciąg od ciebie, których odzyskanie było tylko synonimem co rzeczywisty typ danych? Studenci >> [Wiele] Char *. Char *. Dla rodziców, to prawdopodobnie [czyni dźwięk whooshing]. To dobrze. Char * zaczniemy widzieć na ekranie, tym bardziej jak usunąć napis z naszego słownictwa, przynajmniej jeśli chodzi o faktycznie pisania kodu. Podobnie będziemy zaprzestać stosowania niektórych z tych funkcji, jak wiele bo nasze programy będą się bardziej wyrafinowane. Zamiast po prostu napisać programy, które siedzą tam z polecenia miga, czeka na użytkownika wpisać coś, dostaniesz swoje wejścia z zewnątrz. Na przykład, można je dostać z serii bitów na lokalnym dysku twardym. Będziesz zamiast je w przyszłości z połączenia sieciowego, jakaś witryna gdzieś. Więc odwinąć tej warstwy po raz pierwszy i wyciągnij CS50 Appliance a ten plik nazywa cs50.h, którą już w tym na tydzień #, ale niech rzeczywiście zobaczyć co jest w środku tego. Top pliku w kolorze niebieskim jest tylko cała masa komentarzy: informacje na temat gwarancji i licencjonowania. Jest to rodzaj wspólnej paradygmatu w oprogramowaniu ponieważ wiele programów w tych dniach jest to, co nazywa się open source, co oznacza, że ​​ktoś napisał kod i sprawiło, że łatwo dostępne nie tylko do uruchomienia i do wykorzystania, ale faktycznie czytać i zmieniać i włączać do własnej pracy. Więc to, co już przy użyciu, oprogramowanie open source, choć w formie bardzo małych. Gdybym przewinąć przeszłości komentarzach, choć zaczniemy zobaczyć jakieś bardziej znane rzeczy. Wskazówka na top tutaj, że plik zawiera cs50.h całą masę plików nagłówkowych. Większość z nich, czego nie widzieliśmy wcześniej, ale jedno jest znajome. Która z nich widzieliśmy, choć na krótko, do tej pory? >> [Uczeń] Standardowa biblioteka. Tak, biblioteki standardowej. stdlib.h ma malloc. Kiedy zaczął mówić o dynamicznej alokacji pamięci, które wrócimy do przyszłego tygodnia, jak również, zaczęliśmy w tym pliku. Okazuje się, że bool i prawda i fałsz w rzeczywistości nie istnieją w C per se chyba, że ​​to ten plik tutaj. Mamy już za tydzień w tym stdbool.h tak aby można było używać pojęcia bool, true lub false. Bez tego, to masz coś w rodzaju fałszywego niego i używać int i po prostu arbitralnie założyć, że 0 jest fałszywa i 1 prawda. Jeśli będziemy przewijać dalej, tu jest nasza definicja łańcucha. Okazuje się, jak już wcześniej powiedziałem, że tam, gdzie ta gwiazda jest naprawdę nie ma znaczenia. Można nawet mieć miejsce wszędzie. Mamy w tym semestrze zostały promowanie go jako tego, by wyjaśnić że gwiazda ma do czynienia z typem ale zdaje sobie sprawy, jak często, jeśli nie trochę bardziej powszechne, jest, aby umieścić go tam, ale funkcjonalnie to samo. Ale teraz, gdy czytamy w dół dalej, rzućmy okiem na getInt ponieważ kiedyś, że być może zanim cokolwiek innego w tym semestrze. Oto getInt. To jest co? >> [Uczeń] prototyp. >> To jest tylko prototyp. Często musimy umieścić prototypy na szczytach naszych. Pliki c, ale można również umieścić prototypów w plikach nagłówkowych,. pliki h, jak ten tutaj tak, że gdy piszesz do niektórych funkcji, które chcesz, aby inni ludzie mogli używać, która jest dokładnie w przypadku biblioteki CS50, Ci nie tylko realizować swoje funkcje w coś cs50.c, również umieścić prototypów nie na górze tego pliku, ale na początku pliku nagłówka. Następnie, że nagłówek pliku jest to, co koledzy i przyjaciele m.in. z # include w swoim kodzie. Więc cały ten czas byłeś w tym wszystkie z tych prototypów, skutecznie na początku pliku ale sposób ten obejmuje: mechanizm które zasadniczo kopie i pasty ten plik do siebie. Oto dość szczegółową dokumentację. Mamy dość dużo za pewnik, że getInt dostaje int, ale okazuje się, istnieje kilka przypadków, narożne. Co zrobić, jeśli użytkownik wpisze w szeregu, który jest zbyt duży, trylionów, że po prostu nie może się zmieścić wewnątrz z int? Jakie jest oczekiwane zachowanie? Idealnie, to przewidywalne. Więc w tym przypadku, jeśli rzeczywiście przeczytać drobnym drukiem, będziesz faktycznie zobaczyć, że jeśli linia nie może zostać odczytany, to INT_MAX zwraca. Nigdy nie rozmawialiśmy o tym, ale na podstawie jego kapitalizacji, co to jest chyba? [Uczeń] stała. >> To jest stała. To jakaś specjalna stała pewnie oświadczył w jednym z tych plików nagłówkowych to się wyżej w pliku, a INT_MAX chyba coś około 2 mld euro, Pogląd, że dlatego, że trzeba jakoś oznaczać, że coś poszło nie tak, my, tak, ma 4 miliardy numerów do naszej dyspozycji: -2 mld euro do 2 mld euro, lub dać. No, co jest powszechne w programowaniu jest ukraść tylko jeden z tych numerów, może 0, może 2 miliardy, może -2 miliardów, więc można spędzić jedną z możliwych wartości, tak aby można zobowiązać się do świata że jeśli coś pójdzie nie tak, wrócę to super dużą wartość. Ale ty nie chcesz, aby użytkownik, wpisując coś zagadkowego 234 ..., naprawdę dużą liczbę. Jesteś uogólnienia zamiast jak stała. Tak naprawdę, jeśli były anal w ciągu ostatnich kilku tygodni, za każdym razem nazwałeś getInt, Trzeba było kontroli z jeśli warunek nie typ użytkownika w INT_MAX, lub, bardziej konkretnie, czy INT_MAX powrotu getInt, bo gdyby tak się stało, że w rzeczywistości oznacza, że ​​nie wpisywać. Coś poszło nie tak w tym przypadku. Więc to jest to, co powszechnie znane jako wartości wskaźnikowych, co oznacza po prostu wyjątkowy. Zróbmy teraz skręcić w pliku. C. Plik C istnieje w urządzeniu przez dłuższy czas. I rzeczywiście, urządzenie ma to skompilowane dla Ciebie do tej rzeczy nazwaliśmy kod obiektu, ale to nie ma znaczenia dla Ciebie, gdzie to jest, bo system wie w tym przypadku, w którym jest: urządzenie. Załóżmy teraz, aby przewinąć w dół i zobaczyć jak getInt getInt pracuje cały czas. Tutaj mamy podobne uwagi od wcześniej. Pozwól mi powiększyć tylko części kodu. A co mamy na getInt jest następujące. Nie potrzeba żadnej wejście. Zwraca int, while (true), więc mamy umyślne nieskończoną pętlę, ale prawdopodobnie będziemy łamać z tego jakoś wrócić z wewnątrz tego. Zobaczmy, jak to działa. Wydaje się, że przy użyciu getString w tej pierwszej linii wewnątrz pętli, 166. Teraz jest to dobra praktyka, ponieważ okoliczności, w jakich może GetString powrót Specjalne słowo kluczowe NULL? >> [Uczeń] Jeśli coś pójdzie źle. Jeśli coś pójdzie nie tak. A co może pójść źle podczas rozmowy coś getString? Tak. >> [Uczeń] malloc nie przydzieliło mu wskazówki. Tak. Może malloc zawiedzie. Gdzieś pod maską, GetString dzwoni malloc, która przydziela pamięć, która pozwala magazyn komputerowy wszystkie znaki że użytkownik wpisuje na klawiaturze. I przypuśćmy, że użytkownik miał dużo wolnego czasu i wpisane więcej, na przykład, ponad 2 mld znaków, więcej cech, niż komputer ma nawet RAM. GetString musi być w stanie oznacza, że ​​do Ciebie. Nawet jeśli jest to super, super rzadkością przypadek rogu, musi być w jakiś sposób w stanie obsłużyć, i tak getString, jeśli wróciliśmy i przeczytać jego dokumentację, robi w NULL powrotnych fakt. Więc teraz, jeśli GetString nie zwracając NULL, getInt będzie nie zwracając INT_MAX jak strażnik. Są to tylko ludzkie konwencje. Tylko w ten sposób możesz wiedzieć to sprawa jest czytanie dokumentacji. Miejmy przewinąć w dół, gdzie int jest rzeczywiście dostał. Gdybym przewinąć nieco dalej, w linii 170, mamy komentarz powyżej tych linii. Deklarujemy w 172 int, N i char, C, a następnie ta nowa funkcja, co niektórzy z was natknął się wcześniej, sscanf. To oznacza scanf ciąg. Innymi słowy, daj mi łańcuch i będę go w poszukiwaniu tych informacji, zainteresowania. Co to znaczy? Załóżmy, że mam wpisać dosłownie 123 na klawiaturze, a następnie naciśnij klawisz Enter. Co to jest typ danych 123 gdy są zwracane przez getString? >> [Uczeń] String. To oczywiście łańcuch, prawda? Mam ciąg. Więc 123 jest naprawdę, cytuję-koniec cytatu, 123 z \ 0 na końcu. To nie jest int. To nie liczba jest. To wygląda jak liczba, ale nie jest w rzeczywistości. Więc co getInt zrobić? To musi zeskanować ten ciąg lewej do prawej - 123 \ 0 - i jakoś przekonwertować do rzeczywistej liczby całkowitej. Można dowiedzieć się, jak to zrobić. Jeśli uważasz, że powrót do pset2, to zapewne masz mało wygodne z Cezarem lub Vigenere'a, więc można iteracyjne nad ciąg, można konwertować znaki na wskazówki. Ale do cholery, to jest dużo pracy. Może wywołać funkcję jak sscanf który robi to za Ciebie? Więc sscanf oczekuje argumentu - w tym przypadku nazywa się linia, która jest ciągiem. Następnie należy określić w cudzysłowie, bardzo podobne do printf, czego spodziewać się w tym ciągu. I to, co mówię o to mam się spodziewać liczbę dziesiętną a może charakter. I zobaczymy, dlaczego tak jest za chwilę. I okazuje się, że ten zapis jest teraz przypomina rzeczy zaczęliśmy rozmawiać o nieco ponad tydzień temu. Co to jest & n & c i robi dla nas? >> [Uczeń] Adres n i adres c. Tak. To daje mi adres n i adres c. Dlaczego jest to ważne? Wiesz, że z funkcji w C, możesz zawsze zwraca wartość lub brak wartości. Możesz powrócić int, ciąg znaków, float, char, bez względu, czy możesz wrócić za nieważne, ale można zwrócić tylko jedną rzecz maksymalnie. Ale tutaj chcemy sscanf powrócić mnie może int, liczba dziesiętna, a także znak, a ja dlaczego char w jednej chwili. Ci efektywnie chcą sscanf wrócić dwie rzeczy, ale to nie tylko możliwe, w C. Możesz kontynuować pracę przez przechodzącą w dwa adresy bo jak tylko oddać funkcję dwa adresy co można, że ​​funkcja z nimi zrobić? >> [Uczeń] Napisz do tych adresów. To może napisz do tych adresów. Możesz użyć operacji gwiazdy i tam, do każdego z tych adresów. To coś w rodzaju tego mechanizmu z powrotem drzwi, ale bardzo często do zmiany wartości zmiennych więcej niż jednym miejscu - w tym przypadku, dwa. Zauważcie, jestem sprawdzania == 1, a następnie powrót n jeśli nie w rzeczywistości, ocenia na true. Więc co się dzieje? Technicznie wszystkie naprawdę chcemy się zdarzyć w getInt jest to. Chcemy analizować, by tak rzec, chcemy czytać ciąg - cytuję-koniec cytatu 123 - i jeśli wygląda jak tam numer tam, co mówimy sscanf zrobić jest umieścić tę liczbę - 123 - w tej zmiennej n dla mnie. Dlaczego więc ja rzeczywiście to, jak również? Jaka jest rola sscanf mówiąc można również uzyskać znak tutaj? [Niesłyszalne reakcja studentów] >> przecinek rzeczywiście może zadziałać. Załóżmy, że posiadają pomyślał przez chwilę. Co jeszcze? [Uczeń] To może być NULL. >> Dobra myśl. To może być znak null. To faktycznie nie w tym przypadku. Tak. >> [Uczeń] ASCII. ASCII. Albo daj mi generalizować nawet dalej. C% jest tylko do sprawdzania błędów. Nie chcemy tam być znak po liczbie, ale to, co pozwala mi zrobić jest następujące. Okazuje się, że sscanf, oprócz przechowywania wartości w N i C, w tym przykładzie tutaj , co również nie jest to zwraca liczbę zmiennych to położy wartości w. Więc jeśli tylko wpisać w 123, to tylko% d będzie zgodne, i przechowywane tylko n zostaje jak o wartości 123, i nic nie zostaje wprowadzone wc. C pozostaje wartość śmieci, by tak rzec - śmieci, ponieważ nigdy nie był inicjowany do pewnej wartości. Więc w tym przypadku, sscanf zwraca 1 bo zaludnionych 1 z tych wskaźników, w takim przypadku świetnie, mam int więc zwalniać linię, aby zwolnić pamięć że GetString faktycznie przyznane, a następnie wrócę n, indziej, a jeśli kiedykolwiek zastanawialiście jeżeli Ponów oświadczenie pochodzi, pochodzi z tutaj. Więc jeśli, przeciwnie, mam wpisać 123foo - tylko jakiś przypadkowy ciąg tekstu - sscanf będzie zobaczyć, numer, numer, F, i to będzie umieścić 123 w n; to będzie umieścić f wc, a następnie powrót 2. Więc mamy, po prostu stosując podstawową definicję zachowań sscanf jest, sposób bardzo prosty - oraz, na pierwszy rzut oka skomplikowane, ale pod koniec dnia mechanizm bardzo prosty - powiedzenia ma int i jeśli tak, jest to, że jedyną rzeczą, którą znalazłem? I odstępy o to zamierzone. Jeśli czytać dokumentację sscanf, mówi, że jeśli to kawałek spacją na początku lub na końcu, sscanf zbyt pozwoli użytkownika, niezależnie od przyczyny, trafienie 123 spacji i to będzie zgodne z prawem. Nie krzycz na użytkownika tylko dlatego, że nacisnąć spację na początku lub na końcu, który jest tylko trochę bardziej przyjazny dla użytkownika. Wszelkie pytania następnie na getInt? Tak. >> [Uczeń] Co jeśli po prostu umieścić w char? Dobre pytanie. Co jeśli po prostu wpisane w char jak F i naciśnij Enter bez kiedykolwiek wpisując 123? Co sądzisz zachowanie tej linii kodu byłoby wtedy? [Niesłyszalne odpowiedź uczeń] Tak, więc sscanf może pokryć, że zbyt, ponieważ w tym przypadku nie chodzi o wypełnienie N lub C. To będzie zamiast powrócić 0, w tym przypadku jestem również połowu tego scenariusza ponieważ wartość oczekiwana chcę jest 1. Chcę tylko jeden i tylko jedna rzecz do obsadzenia. Dobre pytanie. Inni? Dobrze. Niech nie przejść przez wszystkie funkcje w tutaj, ale ten, który wydaje się być może pozostały odsetek jest GetString bo okazuje się, że GetFloat, getInt, GetDouble, GetLongLong wszystkie punt dużo ich funkcjonalności do getString. Warto więc przyjrzeć się, jak on jest realizowany tutaj. To wygląda trochę skomplikowane, ale używa tych samych podstaw że zaczęliśmy rozmawiać o ostatnim tygodniu. W getString, który nie bierze argumentu za pustki tutaj i zwraca łańcuch, ja najwyraźniej jestem oświadczając ciąg nazwie buffer. I naprawdę nie wiem, co to ma być używana do jeszcze, ale zobaczymy. Wygląda na to pojemność jest domyślnie 0. Nie bardzo wiesz, gdzie to będzie, nie wiem, co n ma być wykorzystane do jeszcze ale teraz to coraz bardziej interesujące. Zgodnie 243 oświadczamy, int, c. To jest coś w rodzaju głupiego szczegółowo. Char jest 8 bitów, a 8 bitów można zapisać, ile różne wartości? >> [Uczeń] 256. >> 256. Problem jest, jeśli chcesz mieć 256 różnych znaków ASCII, które istnieją jeśli uważasz, że powrót - i nie jest to coś do zapamiętania jest. Ale jeśli myślisz, że powrót do tego wielkiego ASCII wykresu mieliśmy tydzień temu, było w tym przypadku 128 lub 256 znaków ASCII. Wykorzystaliśmy wszystkie wzory maksymalnie 0s i 1s. To jest problem, jeśli chcesz być w stanie wykryć błąd bo jeśli używasz już 256 wartości dla swoich bohaterów, tak naprawdę nie planować, bo teraz nie mam możliwości, mówiąc to nie jest legit charakter, to jest jakiś błędny komunikat. Więc to, co świat robi to oni użyć następnego największą wartość, coś jak int, tak, że masz szaloną liczbę bitów, 32, do 4 miliardów możliwych wartości tak, że można po prostu skończyć używając zasadniczo 257 z nich, 1 z nich ma jakieś specjalne znaczenie jako błąd. Zobaczmy więc, jak to działa. Zgodnie 246, mam duży pętli while wywołującego fgetc, f sens plik, więc getc, a następnie stdin. Okazuje się, to jest po prostu bardziej precyzyjny sposób powiedzenia czytania sygnałów z klawiatury. Standardowa klawiatura oznacza wejście, standardowe wyjście oznacza ekran, i błąd standardowy, który zobaczymy w pset4 oznacza ekran a specjalną część ekranu tak, że nie jest w rzeczywistej produkcji łączyła że przeznaczone do wydrukowania. Ale o tym w przyszłości. Więc fgetc oznacza tylko przeczytać jeden znak z klawiatury i przechowywać go gdzie? Przechowywać go w c. A następnie sprawdzić - więc ja tylko pomocą kilku logicznych spójników tutaj - sprawdzić, czy nie jest równa - \ n, więc użytkownik naciśnij Enter, chcemy zatrzymać w tym punkcie, koniec pętli - i chcemy też sprawdzić na specjalnej stałej EOF, które, jeśli wiesz lub odgadnąć, co się za nim kryje? >> [Uczeń] Koniec pliku. Koniec >> pliku. Jest to rodzaj bezsensowne, bo jeśli piszę na klawiaturze, tam naprawdę nie ma pliku w to, , ale jest to po prostu coś w rodzaju ogólnej termin używany do oznaczać że nic innego nie przychodzi z ludzkiego palce. EOF - koniec pliku. Tak na marginesie, jeśli kiedykolwiek uderzył sterowania D na klawiaturze, a nie, że trzeba jeszcze - masz uderzyć sterowania C - Control D wysyła ta specjalna stała nazywa EOF. Więc teraz musimy tylko trochę dynamicznej alokacji pamięci. Tak więc, jeżeli (n + 1 Zdolność>). Teraz wytłumaczę n. N jak wiele bajtów są aktualnie w buforze, Ciąg, który jesteś aktualnie buduje od użytkownika. Jeśli masz więcej znaków w buforze nie masz zdolności w buforze, intuicyjnie, co musimy zrobić, to przydzielić więcej pojemności. Więc mam zamiar przejrzeć na niektóre z arytmetyki tutaj i skupić się tylko na tej funkcji tutaj. Wiesz co malloc jest lub są przynajmniej ogólnie znane. Zgadnij co realloc robi. >> [Uczeń] Dodaje pamięć. To nie jest całkiem dodanie pamięci. To zmienia alokację pamięci w następujący sposób. Jeśli jest jeszcze miejsce na końcu łańcucha, aby dać Ci więcej tej pamięci niż pierwotnie się daje, a następnie będziesz uzyskać dodatkową pamięć. Więc może po prostu zachować oddanie napis na znaki z powrotem do tyłu do tyłu do tyłu. Ale jeśli to nie jest przypadek, bo czekał zbyt długo i coś losowo ale koleś w pamięci nie ale jest dodatkowa pamięć i tutaj, to w porządku. Realloc zrobi wszystko podnoszenia ciężkich dla Ciebie, przesunąć ciąg czytasz w ten sposób daleko stąd, umieścić go tam, a następnie daje trochę więcej pasa w tym punkcie. Tak z ruchem ręki, chciałbym powiedzieć, że to, co robi GetString jest to zaczyna z małym buforze, może jeden, pojedynczy znak i jeśli użytkownik wpisze w dwóch znaków, GetString kończy wywołanie realloc i mówi jedna postać nie wystarczy, daj mi dwa znaki. Następnie, jeśli przeczytać logiki pętli, to powie użytkownik wpisze w 3 znaków, daj mi teraz nie 2, ale 4 znaków, to dajcie mi 8, a potem dał mi 16 i 32. Fakt, że jestem Podwojenie wydajności każdorazowo Oznacza to, że bufor nie ma rosnąć powoli, to będzie super szybko rosnąć. A co może być zaletą, że? Dlaczego podwajając rozmiar bufora chociaż użytkownik może wystarczy jeden dodatkowy znak z klawiatury? [Niesłyszalne reakcja studentów] >> Co to jest? >> [Uczeń] Nie musisz uprawiać go tak często. Dokładnie. Nie musisz uprawiać go tak często. A to jest po prostu rodzaj jakbyś zabezpieczających swoje zakłady tutaj Pomysł jest, że nie chcesz, aby zadzwonić realloc dużo, ponieważ wydaje się być wolna. Za każdym razem poprosić systemem operacyjnym dla pamięci, jak wkrótce zobaczyć w przyszłym planie problem, że ma tendencję do trochę potrwać. Minimalizując w ten czas, nawet jeśli tracisz trochę przestrzeni, wydaje się być dobrą rzeczą. Ale jeśli przeczytać końcowej części getString tutaj - i znowu rozumienia każdego pojedynczego wiersza nie jest tu tak ważne dziś - zauważyć, że w końcu znów wywołuje malloc i przydziela dokładnie tyle bajtów, ile potrzebuje na ciąg a następnie wyrzuca przez wywołanie darmowe nadmiernie duży bufor jeśli rzeczywiście dostałem dwukrotnie zbyt wiele razy. Tak w skrócie, to jak GetString pracuje cały czas. Wszystko robi to przeczytać jeden znak naraz znowu i znowu i znowu, i za każdym razem potrzebuje dodatkowej pamięci, prosi system operacyjny, dla niej dzwoniąc realloc. Masz pytanie? Dobrze. Atak. Teraz, kiedy rozumiemy wskaźników lub przynajmniej są coraz bardziej zaznajomieni z wskaźników, Rozważmy, jak cały świat zaczyna zwijać jeśli nie dość bronić przed kontradyktoryjnym użytkowników ludzie, którzy próbują włamać się do systemu, ludzie, którzy próbują kraść oprogramowanie obchodząc jakiś kod rejestracyjny że może inaczej trzeba wpisać w. Spójrz na przykład o tym, który jest tylko kod C ma funkcję głównego na dole który wywołuje funkcję foo. I co to jest przejście do foo? [Uczeń] pojedynczy argument. >> [Malan] pojedynczy argument. Więc argv [1], co oznacza pierwsze słowo, które użytkownik wpisze w wierszu polecenia po a.out lub cokolwiek program nazywa. Tak więc w górnej foo ma w char *. Ale char * jest tylko co? >> [Uczeń] string. [Malan] string, więc nie ma nic nowego. Że ciąg jest arbitralnie miano bar. W tej linii tutaj, char c [12], w rodzaju angielskiego półtechnicznej, co to jest linia robi? [Uczeń] Tablica - >> Array? >> [Uczeń] Znaki. Postacie. >> Daj mi tablicę 12 znaków. Tak można nazwać ten bufor. Jest to technicznie nazywa c, ale bufor w programowaniu oznacza tylko kilka przestrzeni że można umieścić kilka rzeczy w. Potem wreszcie memcpy nie używałem wcześniej, ale można się domyślić, co robi. Kopiuje pamięć. Co to robi? Najwyraźniej kopiuje pasek, na wejściu, do C, ale tylko do długości paska. Ale nie jest to błąd tutaj. >> [Uczeń] Musisz sizeof charakter. >> Okay. Technicznie, powinniśmy naprawdę strlen (bar) * sizeof (char)). Zgadza się. Ale w najgorszym przypadku tutaj, załóżmy, że that's - Okay. Potem jest dwa błędy. Więc sizeof (char)); Zróbmy to trochę szerszy. Więc teraz jest jeszcze bug, co jest, co? >> [Niesłyszalne odpowiedź uczeń] Sprawdź, za co? >> [Student] Sprawdź na NULL. Powinniśmy być ogólnie sprawdzanie NULL bo złe rzeczy przytrafiają gdy wskaźnik jest NULL, ponieważ może skończyć się tam, i nie powinny być nigdy zamiar NULL za dereferencji go z operatorem gwiazdy. Tak, że jest dobry. I co jeszcze robimy? Logicznie rzecz biorąc, nie ma tu też wada. [Student] Sprawdź czy argc jest> = do 2. Należy więc sprawdzić, czy argc jest> = 2. Okay, więc nie trzy błędy w tym programie tutaj. Jesteśmy teraz sprawdzenie, czy użytkownik faktycznie wpisane w coś w argv [1]. Good. Więc co trzeci bug? Tak. >> [Uczeń] C może nie być wystarczająco duża. Good. Sprawdziliśmy jeden scenariusz. Mamy niejawnie sprawdzane nie kopiować więcej pamięci niż przekracza długości baru. Więc jeśli ciąg użytkownik wpisze w to 10 znaków, ta mówi tylko skopiować 10 znaków. I to jest w porządku. Ale co, jeśli użytkownik wpisze w słowa w wierszu, jak 20-znakowym słowem? To mówi kopię 20 znaków z paska do czego? C, inaczej znany jako naszego bufora, co oznacza, że ​​po prostu napisał dane do 8 bajtów miejsc, które nie są właścicielami, i nie masz ich w tym sensie, że nigdy nie przydzielonej im. Więc to jest to, co ogólnie znane jako atak przepełnienia bufora lub atak przepełnienia buforu. I jest to atak w tym sensie, że jeśli użytkownik lub program, który dzwoni czynność robi to złośliwie, co faktycznie dzieje się dalej, być może nawet bardzo złe. Warto więc spojrzeć na to zdjęcie tutaj. Ten obraz reprezentuje stos pamięci. Przypomnijmy, że za każdym razem wywołać funkcję masz tę małą ramkę na stosie i znów i znów i innym. I do tej pory, mamy po prostu rodzaj wydobywane są jako prostokąty albo na pokładzie lub na ekranie tutaj. Ale jeśli powiększyć jeden z tych prostokątów, podczas wywołania funkcji foo, okazuje się, że jest coś więcej w środku stosu tej ramki, w tym prostokącie niż tylko X i Y oraz A i B, tak jak my mówimy o konwersji. Okazuje się, że istnieje pewne szczegóły niższego szczebla, wśród nich adres zwrotny. Tak więc okazuje się, gdy główny wywołuje foo, główny musi poinformować foo jaki adres Main jest w pamięci komputera bo inaczej, jak tylko foo odbywa wykonania, jak w niniejszej sprawie, po osiągnięciu tej zamkniętej nawias klamrowy na końcu foo jak do cholery nie wiem gdzie foo kontroli programu ma iść? Okazuje się, że odpowiedź na to pytanie jest w tym czerwonym prostokącie tutaj. Stanowi to wskaźnik, i jest do komputera do czasowego przechowywania na stosie tzw adres głównym, tak, że gdy tylko foo dokonuje realizacji, komputer wie, gdzie i co linia głównego, aby wrócić do. Zapisano wskaźnik ramki dotyczy podobnie do tego. Bar * char reprezentuje tutaj co? Teraz ten niebieski odcinek o to ramka Foo. Co to jest bar? Bar to tylko argument funkcji foo. Więc teraz jesteśmy z powrotem w rodzaju znanego obrazu. Jest więcej rzeczy i więcej rozrywki na ekranie, ale ten niebieski odcinek tylko to, co mamy już rysunek na tablicy na coś takiego swapu. To jest ramka do foo. I jedyną rzeczą, w tym teraz jest bar, który jest ten parametr. Jednak należy co jeszcze w tym w zależności od stosu kod tutaj? [Uczeń] char c [12]. >> [Malan] char c [12]. Warto również zobaczyć 12 kwadratów pamięci przydzielonej do zmiennej o nazwie c, i rzeczywiście, że ma na ekranie. Samej górze jest c [0], a następnie autor tego schematu nie przeszkadzało rysowania wszystkich kwadratów, ale są tam rzeczywiście 12 bo jeśli przyjrzeć się na dole po prawej, c [11], jeśli liczyć od 0 jest 12 takich bajt. Ale tu jest problem. W którym kierunku jest c rośnie? Rodzaju odgórne, jeśli zaczyna się na górze i rośnie na dnie. To nie wygląda na to, że zostawili sobie dużo pas tutaj w ogóle. Mamy trochę malował się w kąt, i że c [11] jest prawo przeciwko baru, który jest zaraz na przeciw ofert wskaźnik ramki, który jest zaraz na przeciw adres zwrotny. Nie ma więcej miejsca. Więc co jest implikacja wtedy jeśli spieprzysz i próbie odczytu 20 bajtów do bufora 12-bajtowy? Gdzie są te 8 dodatkowych bajtów pójdzie? >> [Uczeń] Inside - Wszystko wewnątrz, z których część jest bardzo ważne. I najważniejsze, potencjalnie, jest czerwone pole tam, adres zwrotny, bo załóżmy, że przypadkowo lub adversarially zastąpić te 4 bajty, wskaźnik ten adres, nie tylko z odpadkami, ale z kilkoma że dzieje stanowią aktualny adres w pamięci. Co jest implikacja, logicznie? >> [Uczeń] Funkcja ma zamiar powrócić do innego miejsca. Dokładnie. Kiedy powraca Foo i przeboje, które nawiasem klamrowym, program będzie kontynuować nie wracać do głównego, to będzie powrót do tego, co jest w tym adres czerwonym polu. W przypadku rejestracji obchodzą oprogramowania co jeśli adres, który jest zwracane do jest funkcja, która normalnie jest wywoływana po tym, jak zapłacił za oprogramowanie i wprowadzony kod rejestracyjny? Możesz sortować sztuczka do komputera nie będzie tutaj, ale zamiast dzieje się tutaj. Lub jeśli jesteś naprawdę mądry, przeciwnik może faktycznie wpisać na klawiaturze, na przykład, nie rzeczywiste słowo, nie 20 znaków, ale przypuszczam, że ona faktycznie rodzaje w niektóre znaki, które reprezentują kod. I nie będzie to kod C, to faktycznie będzie to znaki które reprezentują binarnego kodu maszynowego, 0s i 1s. Załóżmy jednak, że są one na tyle sprytny, aby to zrobić, jakoś wkleić do getString coś polecenia, które jest zasadniczo skompilowany kod, a ostatnie 4 bajty nadpisać że adres zwrotny. A co to ma adres wejściowy zrobić? To faktycznie przechowuje w czerwonym prostokącie adres pierwszego bajtu bufora. Więc trzeba być naprawdę sprytny, a to jest dużo prób i błędów dla złych ludzi tam, ale jeśli można dowiedzieć się, jak duża to bufor jest tak, że w ciągu ostatnich kilku bajtów wejściowych podać do programu stało się równoznaczne z adresem początku buforze, możesz to zrobić. Jeśli mówimy, że normalnie przywitać i \ 0, to co kończy się w buforze. Ale jeśli jesteśmy bardziej sprytny i zapełnić bufor z tym, co my nazywamy ogólnie kod ataku - AAA, atak, atak, atak - gdy jest to po prostu coś, że robi coś złego, co się dzieje, jeśli jesteś naprawdę sprytny, może to zrobić. W czerwonym polu o to ciąg liczb - 80, C0, 35, 08. Zauważ, że jest zgodny z numerem, który jest tutaj. Jest to w odwrotnej kolejności, ale o tym jakiś czas innych. Zauważ, że ten adres zwrotny został celowo zmieniony dorównać adres tutaj, nie adres main. Więc jeśli zły facet jest super inteligentny, on lub ona będzie m.in. w tym kodzie ataku coś jak usunięcie wszystkich plików użytkownika lub skopiować hasła lub utworzyć konto użytkownika, które można następnie zalogować się - nic. I to zarówno niebezpieczeństwo i moc C. Ponieważ masz dostęp do pamięci poprzez wskaźniki i można więc napisać, co chcesz do pamięci komputera, można zrobić komputer rób co chcesz po prostu po to skakać w swojej własnej pamięci. I tak do tej pory tak wiele programów i tak wiele stron internetowych, które są zagrożone sprowadzają się do osób korzystających z tego. A to może wydawać się super ataku wyrafinowany, ale nie zawsze zaczynać w ten sposób. Rzeczywistość jest taka, że ​​to, co źli ludzie zwykle zrobić to, czy jest to program w linii poleceń lub program GUI lub strona internetowa, po prostu rozpocząć świadczenie bzdury. Wpisujesz w naprawdę dużym słowa w polu wyszukiwania i naciśnij Enter, i czekać, aby zobaczyć, czy strona wywala albo czekać, aby zobaczyć, czy program przejawia pewien komunikat o błędzie bo jeśli będziesz miał szczęście, jak zły facet i podać jakiś szalony wejście że wywala program, oznacza to, że programista nie przewidział swoje złe zachowanie, co oznacza, że ​​można prawdopodobnie z dość wysiłku, tyle prób i błędów, dowiedzieć się, jak prowadzić bardziej precyzyjnego ataku. Tak samo częścią bezpieczeństwa jest nie tylko całkowicie uniknąć tych ataków ale ich wykrywania i rzeczywiście patrząc na dzienniki i zobaczyć, co szalone wejścia mają osoby wpisane na swojej stronie, jakie terminy wyszukiwania są osoby wpisane na swojej stronie w nadziei, że brzegi trochę bufor. A to wszystko sprowadza się do prostych podstaw Co jest tablica i co to oznacza dla alokacji i wykorzystania pamięci. Podobne do tego, wtedy też to jest. Miejmy tylko spojrzeć wewnątrz dysku twardego po raz kolejny. Pamiętacie z tydzień lub dwa temu, że podczas przeciągania plików do kosza lub kosza, co się dzieje? >> [Uczeń] Nic. >> Absolutnie nic, prawda? Ostatecznie jeśli brakować miejsca na dysku, Windows lub Mac OS rozpocznie usuwanie pliki. Ale jeśli przeciągnij coś tam, że w ogóle nie jest bezpieczne. Wszystko twój współlokator lub przyjaciel lub członek rodziny ma zrobić, to kliknij dwukrotnie i, voila, tam wszystkie fragmentaryczne pliki, które próbowały usunąć. Większość z nas, przynajmniej wiem, że trzeba kliknąć prawym przyciskiem myszy lub sterowania kliknij i pusty kosz lub coś w tym stylu. Ale nawet wtedy nie dość rade ponieważ to, co się dzieje, gdy masz plik na dysku twardym która reprezentuje jakiś dokument Word lub jakiś JPEG, a to oznacza dysk twardy, i powiedzmy, że ta drzazga reprezentuje tutaj ten plik, i to w składzie całą masę 0s i 1s. Co się dzieje, gdy nie tylko przeciągnąć plik do kosza lub kosza ale też go opróżnić? Sortuj niczego. To nie jest absolutnie nic nie jest teraz. Teraz jest to po prostu nic, bo trochę coś się dzieje w formie tabeli. Więc jest jakiś rodzaj bazy danych lub tabeli wewnątrz pamięci komputera który zasadniczo zawiera jedną kolumnę dla plików nazwisk i kolumny dla plików "lokalizacji, gdzie to może być lokalizacja 123, tylko liczba losowa. Więc może mamy coś x.jpeg i lokalizacja 123. Co dzieje się wtedy, gdy faktycznie opróżnić kosz? Że odchodzi. Ale co nie odejdzie to 0s i 1s. Więc co jest potem połączenie pset4? Cóż, z pset4, tylko dlatego, że przypadkowo usunięte z karty Compact Flash że miał wszystkie z tych zdjęć lub po prostu dlatego, że przez pecha został uszkodzony nie oznacza, że ​​0s i 1s nie są tam nadal. Może niektóre z nich giną dlatego, że coś jest zepsute w tym sensie, że niektóre stały 1s i 0s 1s stał 0s. Złe rzeczy mogą się zdarzyć z powodu wadliwego oprogramowania lub wadliwego sprzętu. Ale wielu z tych bitów, może nawet 100% z nich wciąż tam są. Tyle tylko, że komputer lub aparat nie wie, gdzie rozpoczął JPEG1 i gdzie JPEG2 zaczęło. Ale jeśli, programista, wiem z nieco doświadczonych, gdzie te pliki JPEG są lub jak wyglądają, dzięki czemu można analizować 0s i 1s i powiedzieć JPEG, JPEG, można napisać program w zasadzie tylko za lub pętli while odzyskuje każdy z tych plików. Więc lekcja jest więc bezpiecznie rozpocząć usuwanie plików jeśli chcesz tego uniknąć całkowicie. Tak. [Uczeń] Jak to jest napisane na komputerze że masz więcej pamięci niż wcześniej? Miał więcej pamięci niż wcześniej - >> [uczeń] Więcej dostępnej pamięci. Oh. Dobre pytanie. Dlaczego więc po opróżnieniu kosza nie komputer powiedzieć że masz więcej wolnego miejsca niż wcześniej? W skrócie, bo kłamie. Bardziej technicznie, masz więcej miejsca, bo teraz pan powiedział można umieścić inne rzeczy, gdzie ten plik kiedyś. Ale to nie znaczy, bity idą dalej, oraz, że nie oznacza to, że ulegają zmianie bitów wszystkich 0s, na przykład dla ochrony. Tak dla odmiany, jeśli bezpiecznie usunąć pliki lub fizycznie zniszczyć urządzenie, że naprawdę jest jedynym sposobem czasami obejść. Więc dlaczego nie możemy pozostawić na tej notatce semi-straszny, i zobaczymy w poniedziałek. [Oklaski] [CS50.TV]