[MUZYKI] DOUG LLOYD: OK, więc sugestia przed rozpoczęciem tutaj. Jeśli nie oglądałem film na wskaźnikami możesz to zrobić w pierwszej kolejności. Bo ten film jest inny sposób pracy ze wskaźnikami. Więc to będzie mówić o niektórych pojęć które obejmują w wskaźnikami wideo, a my jesteśmy będzie połysk przez nich teraz, przy założeniu, że są już rodzaj rozumieć. Więc to jest tylko twój uczciwe ostrzeżenie że jeśli widzisz ten film i nie widziałem wskaźniki film, to może coś w rodzaju latać nad głową trochę. I tak może być lepiej aby obejrzeć go w tej kolejności. Więc już widzieliśmy jednego sposób pracy ze wskaźnikami, co deklarujemy zmienna, a następnie Oświadczam, innej zmiennej, wskaźnik zmienny, który wskazuje na to. Więc stworzyliśmy zmienna o nazwie, mamy utworzył drugą zmienną o nazwie i wskazać, że druga zmienna na tym pierwszym. Ten rodzaj ma Problem jednak, bo to wymaga od nas, aby dokładnie wiedzieć, ile pamięci jesteśmy będzie potrzebował moment nasz program jest skompilowany. Dlaczego? Bo musimy być w stanie wymienić lub zidentyfikowania wszystkich możliwych zmiennych możemy spotkać. Możemy mieć tablicę, która może być w stanie utrzymać wiele informacji, ale to nie jest jeszcze dokładnie tyle precyzyjne. Co zrobić, jeśli nie wiemy, co jeśli nie mamy pojęcia ile będziemy potrzebować w czasie kompilacji? Albo co jeśli nasz program trwać naprawdę długo, przyjmując różne użytkownika danych, a tak naprawdę nie możemy Szacujemy, czy jesteśmy będzie potrzebował 1000 jednostek? To nie tak, możemy powiedzieć, w wierszu poleceń wprowadzić jak najwięcej przedmiotów myślisz, że musisz. No i co, czy to przypuszczenie jest nie tak? Dynamiczna alokacja pamięci rodzaj pozwala nam drogę obejść tego konkretnego problemu. A sposób, w jaki to robi Jest przy użyciu wskaźników. Możemy wykorzystać wskaźniki do uzyskać dostęp do dynamicznie przydzielone pamięci, pamięci, która jest przydzielone w programie jest uruchomiony. To nie jest przydzielony w czasie kompilacji. Kiedy dynamicznie przydzielać Pamięć pochodzi z basenu znane jako pamięci na stercie. Wcześniej cała pamięć mamy Pracuję z w toku przyjeżdża z puli pamięci zwany stos. Dobrym sposobem na ogół należy mind-- i tej zasady nie zawsze są prawdziwe, ale prawie prawie Zawsze trzyma true-- jest, że każdy Czas podać nazwę zmiennej it Prawdopodobnie mieszka na stosie. I za każdym razem tego nie zrobisz dać zmiennej nazwę, które można zrobić z pamięci dynamicznej alokacji, żyje na stercie. Teraz jestem trochę prezentuje to jako jeśli jest te dwie pule pamięci. Ale może widzieliście to schemat, który jest na ogół reprezentacją co Pamięć wygląda, a my nie będziemy dbać o wszystko rzeczy na górze i na dole. Co dbamy o to ta część w środkowa tutaj, sterty i stosu. Jak widać przez patrząc na tym schemacie, Nie są one w rzeczywistości dwa oddzielne pule pamięci. To jedna wspólna pula pamięci gdzie zacząć, w tym wizualne rozpocząć na dole i zacząć zapełniać od dołu stosu, a ty rozpoczyna się na górze i rozpocząć tankowanie z góry na dół z hałdy. Ale to naprawdę jest sam basen, to tylko różne miejsca, różne lokalizacje w pamięci, które są przydzielane. A może zabraknie pamięci, albo o sterta przejść całą drogę na dno, lub stos przejść całą drogę na górę, lub o sterty i stosu spotkać się ze sobą. Wszystkie te mogą być warunki które powodują swój program zabraknie pamięci. Miejcie to na uwadze. Kiedy mówimy o sterta i stos tak naprawdę mówimy o sam ogólny fragment pamięci, po prostu różne części tej pamięci. Jak więc się dynamicznie przydzielona pamięć, w pierwszej kolejności? Jak działa nasz program się pamięci, jak to działa? Cóż C zapewnia funkcję o nazwie malloc, przydzielania pamięci, które można nawiązać połączenie, i przechodzą w jak wiele bajtów pamięci, które chcesz. Więc, gdy Twój program jest uruchomiony i chcesz, aby czas pracy całkowitą, możesz Mallock cztery bajty Pamięć, malloc nawiasach cztery. Mallock przejdzie patrząc przez hałdy, bo jesteśmy dynamicznie przydzielania pamięci, i wróci do Ciebie wskaźnik do tej pamięci. To nie daje ci tego memory-- nie daje mu nazwę, to daje wskaźnik do niego. A więc dlatego znów powiedziałem że ważne jest, aby być może oglądałem film wskaźniki zanim się zbyt daleko do tego. Więc malloc będzie oddać wskaźnik. Jeśli Mallock nie daje żadnej Pamięć dlatego, że zabrakło, będzie to oddać pustego wskaźnika. Pamiętasz, co się stanie, jeśli spróbować dereference wskaźnikiem NULL? Cierpimy usterki seg, prawda? To chyba nie jest dobry. Dlatego za każdym razem, kiedy nawiązać połączenie malloc Cię zawsze, zawsze należy sprawdzić, czy wyżeł dał kopii jest zerowy. Jeśli tak jest, trzeba zakończyć swój program bo jeśli spróbujesz i dereference null pointer idziesz cierpieć błąd segmentacji i Twój program jest będzie tak upaść. Jak więc statycznie uzyskać liczbę całkowitą? int x. Mamy prawdopodobnie zrobisz kilka razy, prawda? To tworzy zmienną x, że mieszka na stosie. W jaki sposób możemy dynamicznie uzyskać liczbę całkowitą? Int gwiazda px równa malloc 4. Lub więcej odpowiednio powiedzielibyśmy int gwiazda px równa malloc rozmiar int, po prostu wyrzucić niektóre mniej Magiczne liczby wokół naszego programu. To będzie dla nas, aby uzyskać cztery bajty pamięci ze sterty, i wskaźnik mamy Wróć do niego jest nazywany px. A potem, tak jak mamy zrobione wcześniej mamy może dereference px do dostępu do tej pamięci. W jaki sposób możemy uzyskać liczbę całkowitą od użytkownika? Można powiedzieć, int x równa się int. To całkiem proste. Co zrobić, jeśli chcemy stworzyć tablicę od x pływaków, które żyją na stosie? unosić stack_array-- to nazwa naszych array-- nawiasach kwadratowych x. To stworzy dla nas tablicy od x pływaków, które żyją na stosie. Możemy stworzyć tablicę pływaków który żyje na stercie, też. Składnia może wyglądać trochę bardziej kłopotliwe, ale można powiedzieć, pływak gwiazda heap_array równa malloc x razy większy od pływaka. Muszę wystarczająco dużo miejsca do przechowywania x zmiennoprzecinkowych. Więc muszę powiedzieć, 100 pływaki lub 1000 pływaki. A więc w tym przypadku byłoby 400 bajtów do 100 pływaków, lub 4000 bajtów do 1000 pływaków, ponieważ każdy pływak zajmuje cztery bajty przestrzeni. Po wykonaniu tej czynności można używać nawias kwadratowy składni na heap_array. Tak jak bym na stack_array, ja mogą uzyskać dostęp do jej elementów oddzielnie za pomocą heap_array zero, heap_array jeden. Ale przypominam powód możemy to zrobić Jest tak, ponieważ nazwa tablicy w C jest naprawdę wskaźnik do Pierwszy element tej tablicy jest. Tak więc fakt, że jesteśmy uznającej Tablica pływaków na stosie tutaj w rzeczywistości jest nieco mylące. Naprawdę są w Druga linia kodu nie także tworzenie wskaźnik do kawałka pamięci, które następnie popracować z. Tu jest duży problem z dynamicznie przydzielana pamięć choć, i to dlatego, że to naprawdę ważne, aby rozwijać dobre nawyki podczas pracy z nim. W przeciwieństwie statycznie oświadczył pamięć, pamięć nie jest automatycznie zwracana do System, gdy funkcja jest wykonywana. Więc jeśli mamy głównym i Głównym wywołuje funkcję f, gdy f wykończeń cokolwiek to robi i zwraca sterowanie programem powrotem do głównego wszystkie pamięci że f jest stosowany zwrócona. Może on być ponownie wykorzystywany za pośrednictwem innego programu, lub inną funkcją jest wywoływana później w głównym. Można go użyć tej samej pamięci na nowo. Jeśli dynamicznie przydzielić pamięci choć trzeba wyraźnie powiedzieć System, że jesteś z nim zrobić. To będzie trzymać się go dla Ciebie, które mogłyby prowadzić do problemów z was na wyczerpaniu pamięci. A w rzeczywistości czasami odnoszą to jako przeciek pamięci. I czasami te wycieki pamięci w rzeczywistości może być bardzo niszczące na wydajność systemu. Jeśli jesteś częstym użytkownikiem www można korzystać z niektórych przeglądarek internetowych, i nie będę wymieniać nazwisk tutaj, ale istnieje kilka przeglądarek internetowych tam które są notorycznie faktycznie konieczności wycieki pamięci, że nie dostać stałe. A jeśli pozostawić otwartą przeglądarkę Przez bardzo długi okres czasu, dzień i dni, lub tygodni, czasami można zauważyć, że system jest systemem bardzo, bardzo powoli. A powodem tego jest to, że przeglądarka przeznaczyła pamięć, ale wtedy nie powiedział systemu że to z nim zrobić. I tak, że pozostawia mniej pamięci dostępne dla wszystkich innych programów aby się podzielić, bo jesteś leaking-- tego przeglądarkę internetową Program jest wyciek pamięci. Jak dajemy pamięć powrotem kiedy mamy z nim zrobić? No na szczęście jest to bardzo prosty sposób to zrobić. My po prostu uwolnić go. Jest to funkcja zwana wolna, przyjmuje wskaźnik do pamięci, i jesteśmy dobrze iść. Więc powiedzmy, że jesteśmy w środek naszego programu, chcemy malloc 50 znaków. Chcemy malloc tablicę, która może w stanie utrzymać 50 znaków. A gdy mamy wskaźnik z powrotem do że nazwa tego wskaźnika jest słowo. Robimy co jesteśmy zamiar zrobić ze słowem, a następnie, gdy jesteśmy odbywa się po prostu uwolnić go. A teraz wróciliśmy te 50 bajtów pamięci z powrotem do systemu. Niektóre inne funkcje mogą z nich korzystać. Nie musimy martwić się o cierpienie wyciek pamięci, ponieważ uwolnił słowo. Daliśmy pamięć z powrotem, tak skończymy pracę z nim. Tak więc są trzy złotych zasad, które powinny należy pamiętać, gdy jesteś dynamicznego przydzielania pamięci z malloc. Każdy blok pamięci Ci malloc musi zostać uwolnione Zanim program zakończy uruchomiony. Się ponownie w urządzeniu lub w IDE tego rodzaju dzieje się dla Ciebie tak kiedy you-- stanie się to tak gdy program jest zakończony, cała pamięć zostanie zwolniona. Ale to jest na ogół dobre kodowanie Praktyka zawsze, kiedy skończysz, uwolnić, co masz mallocd. Powiedział, że tylko rzeczy, które masz mallocd powinny zostać uwolnione. Jeśli statycznie zadeklarować całkowita, int x średnik, że mieszka na stosie, to nie to chce uwolnić x. Tak więc tylko rzeczy, które już mallocd powinny zostać uwolnione. I wreszcie, nie wolny coś dwa razy. To może prowadzić do kolejna dziwna sytuacja. Więc wszystko, co masz mallocd musi być uwolniona. Jedyne rzeczy, które zostały malloc powinny zostać uwolnione. I nie zrobić bezpłatne coś dwa razy. Więc chodźmy na przykładzie tutaj co niektóre dynamicznie przydzielane Pamięć może wyglądać mieszane w niektóre pamięci statycznej. Co może się zdarzyć tutaj? Zobacz, jeśli można śledzić wzdłuż i odgadnąć, co jest będzie się działo jak idziemy przez wszystkie te linie kodu. Tak więc możemy powiedzieć, int m. co się tutaj stało? Więc jest to całkiem proste. Utworzyć zmienną całkowitą o nazwie m. I kolor to zielony, bo to kolor że mogę używać, kiedy mówię o zmiennych całkowitych. Jest to okno. To się nazywa m, i można Sklep z liczbami całkowitymi w jej wnętrzu. Co jeśli to powiedzieć, int star? Dobrze, że jest dość podobna. Tworzę pole nazywa. Jest w stanie utrzymać int gwiazdy, wskaźniki do liczb całkowitych. Więc jestem kolorowanie to Zielona-owski, jak również. Wiem, że ma to coś do czynienia z liczbą całkowitą, ale sama nie jest liczbą całkowitą. Ale to prawie ten sam pomysł. Stworzyłem okno. Obie te prawa teraz mieszkam na stosie. Dałem im obie nazwy. int gwiazda b równa malloc rozmiar int. Ten może być trochę trudne. Poświęć chwilę i pomyśleć o tym, co spodziewałby się zdarzyć na tym schemacie. int gwiazda b równa malloc rozmiar int. No to nie wystarczy utworzyć jedno pole. To rzeczywiście tworzy dwa pola. A to wiąże, również ustanawia punkt w związku. Mamy przydzielony jeden blok pamięci na stercie. Zauważ, że w prawym górnym rogu okno nie ma nazwy. Mamy mallocd go. Istnieje on na stercie. Ale b ma imię. Jest to wskaźnik o nazwie zmiennej b. Że mieszka na stosie. Więc jest to kawałek pamięci który wskazuje na inny. b zawiera adres z tego bloku pamięci. To nie ma nazwy inaczej. Ale wskazuje na to. Więc, gdy mówimy, int gwiazda b równa Rozmiar malloc int, że tam, że strzałka, która pojawiła się na tam po prawej stronie, że cała sprawa, Będę musiał się wydawać znowu, jest to, co się dzieje. Wszystko to dzieje się w że jednej linii kodu. Teraz będziemy mieli trochę więcej znowu proste. A równa ampersand m. Pamiętasz, co się równa znaku & m jest? Dobrze, że to dostaje adres M. Lub umieścić bardziej schematycznie, a punkty do m. A równa się b. OK, więc o jeszcze jeden. A równa się b. Co się stanie na wykresie tym razem? Dobrze pamiętam, że prace operatora przypisania przez przypisanie wartości na Prawo do wartości po lewej stronie. Więc zamiast skierowana M, A teraz wskazuje w tym samym miejscu, że B punktów. A nie wskazują na B, A wskazuje, gdzie b punktów. Jeśli szpiczasty do b, które były równe ampersand b. Ale zamiast równa b prostu Oznacza to, że i b są teraz wskazując tym samym adresem, ponieważ wewnątrz b jest tylko adres. Teraz wewnątrz a jest tego samego adresu. m wynosi 10, prawdopodobnie Najprostszą rzeczą zrobiliśmy w trochę. Umieścić 10 w polu. Gwiazda b równa m plus 2, pamiętam z Wskaźniki wideo, co nasza gwiazda b oznacza. Jedziemy do wyłuskiwania b i umieścić jakaś wartość w tym miejscu pamięci. W tym przypadku 12. Kiedy więc dereference punktu Przypomnijmy, że po prostu podróżować w dół strzałkę. Albo innymi słowy, mamy przejść do tego adresu pamięci i manipulować nim w jakiś sposób. Kładziemy jakąś wartość tam. W tym przypadku gwiazdy b M plus 2 równa jest po prostu przejść do zmiennej wskazywanej przez b, przejść do pamięci wskazywanego przez b, i umieścić m plus 2 tam, 12. Teraz uwolnić b. Co się dzieje, kiedy zwolnić b? Pamiętaj, co powiedziałem wolne środki. Co ja mówię, kiedy zwolnić b? Skończyłem pracę z nim, prawda? I w zasadzie zrezygnować z pamięci. Daję go z powrotem do systemu. Nie potrzebuję już tego jest co mam im powiedzieć, OK? Teraz, jeśli powiem, star wynosi 11 prawdopodobnie można już powiedzieć, że coś złego będzie się działo tutaj, prawda? I rzeczywiście, jeśli Próbowałem, że prawdopodobnie poniósłby winy segmentacji. Bo teraz, choć wcześniej, że fragment pamięci było coś, co miałem dostęp do nich w tym momencie teraz mam dostępu do pamięci, że nie jest dla mnie prawnego dostępu. A jak będzie prawdopodobnie pamiętam, kiedy dostęp do pamięci że nie powinniśmy dotykać, to jest najczęstszą przyczyną z segmentacji przyczepić. I tak mój program będzie katastrofy, gdy starałem się to zrobić. Więc jeszcze raz, że to dobry pomysł, aby uzyskać dobry praktyka i dobre nawyki zakorzenione podczas pracy z malloc i wolna, tak, że nie cierpią segmentacji błędy, i że używasz Twój dynamicznie przydzielane Pamięć odpowiedzialnie. Jestem Doug Lloyd to CS50.