1 00:00:00,000 --> 00:00:02,000 [Powered by Google Translate] [Валгринд] 2 00:00:02,000 --> 00:00:05,000 [Нејт Хардисон, Универзитет Харвард] 3 00:00:05,000 --> 00:00:07,000 Ово је ЦС50, ЦС50.ТВ] 4 00:00:07,000 --> 00:00:10,000 Неке од најтежих грешака у Ц програмима 5 00:00:10,000 --> 00:00:13,000 долазе из лошег управљања меморијом. 6 00:00:13,000 --> 00:00:15,000 Постоји велики број начина да сјебемо ствари, 7 00:00:15,000 --> 00:00:17,000 укључујући доделу погрешну количину меморије, 8 00:00:17,000 --> 00:00:20,000 заборављајући да се покрене променљиве 9 00:00:20,000 --> 00:00:23,000 писања пре или после краја бафера, 10 00:00:23,000 --> 00:00:25,000 и ослобађање држати меморијске више пута. 11 00:00:25,000 --> 00:00:28,000 Симптоми варирају од повремених падова 12 00:00:28,000 --> 00:00:30,000 да мистериозно преписани вредности, 13 00:00:30,000 --> 00:00:34,000 често на местима и временима далеко од оригиналног грешке. 14 00:00:34,000 --> 00:00:37,000 Трасирање посматрану проблем назад на основни узрок корена 15 00:00:37,000 --> 00:00:39,000 може бити изазов, 16 00:00:39,000 --> 00:00:42,000 али срећом постоји програм који се зове корисна Валгринд 17 00:00:42,000 --> 00:00:44,000 који може да уради много да помогне. 18 00:00:44,000 --> 00:00:47,000 >> Покренете програм под Валгринд ће омогућити 19 00:00:47,000 --> 00:00:50,000 обимна провера издвајања гомилу меморије и приступа. 20 00:00:50,000 --> 00:00:53,000 Када Валгринд детектује проблем, то вам даје непосредан, 21 00:00:53,000 --> 00:00:56,000 директних информација која вам омогућава да 22 00:00:56,000 --> 00:00:58,000 лакше пронашли и решили проблем. 23 00:00:58,000 --> 00:01:01,000 Валгринд такође извештаје о мање смртоносна меморијских питањима, 24 00:01:01,000 --> 00:01:04,000 као што су меморијске цурења, распоређивању гомили меморије, 25 00:01:04,000 --> 00:01:07,000 и заборављање да га ослободе. 26 00:01:07,000 --> 00:01:10,000 Као наш компајлера, кланг, у нашој дебуггер, гдб, 27 00:01:10,000 --> 00:01:14,000 Валгринд је слободан софтвер, и то је инсталиран на уређају. 28 00:01:14,000 --> 00:01:16,000 Валгринд ради на свом бинарном извршне, 29 00:01:16,000 --> 00:01:20,000 није ваш ц или х изворни код.., 30 00:01:20,000 --> 00:01:23,000 па будите сигурни да сте саставили до-то-дате копију програма 31 00:01:23,000 --> 00:01:25,000 коришћењем цланг или Маке. 32 00:01:25,000 --> 00:01:28,000 Затим, ради свој програм под Валгринд може бити 33 00:01:28,000 --> 00:01:32,000 тако једноставно као само префикс стандардну програмску команду речју валгринд, 34 00:01:32,000 --> 00:01:35,000 која покреће Валгринд и покреће програм унутар њега. 35 00:01:35,000 --> 00:01:38,000 Приликом покретања, Валгринд се нека сложена 36 00:01:38,000 --> 00:01:41,000 јиггеринг за конфигурисање извршну за меморијске провера, 37 00:01:41,000 --> 00:01:44,000 тако да може да потраје мало да устане и ради. 38 00:01:44,000 --> 00:01:48,000 Програм ће затим извршити нормално, било је много спорије, 39 00:01:48,000 --> 00:01:52,000 а када се заврши, Валгринд ће одштампати резиме својој меморији употребе. 40 00:01:52,000 --> 00:01:58,000 Ако све прође добро, то ће изгледати отприлике овако: 41 00:01:58,000 --> 00:02:01,000 У овом случају, / цлеан_програм. 42 00:02:01,000 --> 00:02:04,000 је пут до програма желим да бежим. 43 00:02:04,000 --> 00:02:06,000 И док овај не предузима никакве аргументе, 44 00:02:06,000 --> 00:02:09,000 ако јесте ја бих их само тактика на крају команде, као и обично. 45 00:02:09,000 --> 00:02:12,000 Чиста програм је само глупо мали програм сам креирао 46 00:02:12,000 --> 00:02:15,000 који додељује простор за блок Интс на гомили, 47 00:02:15,000 --> 00:02:19,000 ставити неке вредности унутар њих, и ослобађа цео блок. 48 00:02:19,000 --> 00:02:23,000 То је оно што снимате за, без грешака и без пукотина. 49 00:02:23,000 --> 00:02:27,000 >> Други важан показатељ је укупан број бајтова додељених. 50 00:02:27,000 --> 00:02:32,000 У зависности од програма, ако вам издвајања су у мегабајтима или више, 51 00:02:32,000 --> 00:02:34,000 вероватно радиш нешто погрешно. 52 00:02:34,000 --> 00:02:37,000 Да ли непотребно одлагање дупликате? 53 00:02:37,000 --> 00:02:40,000 Да ли користите гомилу за складиштење, када би било боље да се користи стек? 54 00:02:40,000 --> 00:02:43,000 Дакле, меморијске грешке могу бити заиста зао. 55 00:02:43,000 --> 00:02:46,000 Што више отоврена они проузрокују спектакуларне падове, 56 00:02:46,000 --> 00:02:49,000 али чак и тада још увек може бити тешко да одредимо 57 00:02:49,000 --> 00:02:51,000 шта је тачно довело до несреће. 58 00:02:51,000 --> 00:02:54,000 Више подмукло, програм са меморијском грешке 59 00:02:54,000 --> 00:02:56,000 и даље може саставити чисто 60 00:02:56,000 --> 00:02:58,000 и даље може да изгледа исправно раде 61 00:02:58,000 --> 00:03:01,000 јер сте успели да добијете среће већину времена. 62 00:03:01,000 --> 00:03:04,000 Након неколико успешних резултата "," 63 00:03:04,000 --> 00:03:07,000 само помислити да је судар је случајност рачунара, 64 00:03:07,000 --> 00:03:10,000 али рачунар није у реду. 65 00:03:10,000 --> 00:03:13,000 >> Покретање Валгринд може да вам помогне да нађем узрок видљивих меморијских грешака 66 00:03:13,000 --> 00:03:18,000 као и пронашли грешке које вребају чак и не знамо о томе. 67 00:03:18,000 --> 00:03:22,000 Сваки пут Валгринд детектује проблем, штампа информације о томе шта је то приметио. 68 00:03:22,000 --> 00:03:24,000 Свака ставка је прилично кратак - 69 00:03:24,000 --> 00:03:27,000 извор линија увредљивим наставе, у чему је проблем, 70 00:03:27,000 --> 00:03:30,000 и мало информација о меморији укључена - 71 00:03:30,000 --> 00:03:34,000 али често је довољно информација да скренем вашу пажњу на право место. 72 00:03:34,000 --> 00:03:37,000 Ево примера Валгринд ради на програму бугги 73 00:03:37,000 --> 00:03:40,000 да ли неважећи читају хеап меморије. 74 00:03:40,000 --> 00:03:49,000 Ми не видимо грешке или упозорења у компилацију. 75 00:03:49,000 --> 00:03:53,000 Ух-ох, грешка резиме каже да постоје две грешке - 76 00:03:53,000 --> 00:03:56,000 два неисправна читања величине 4 - бајта, тј. 77 00:03:56,000 --> 00:04:01,000 Оба лоше чита догодила у главном функцији инвалид_реад.ц, 78 00:04:01,000 --> 00:04:04,000 први на реду 16 а други на линији 19. 79 00:04:04,000 --> 00:04:06,000 Погледајмо кода. 80 00:04:06,000 --> 00:04:11,000 Изгледа као први позив да принтф покушава да прочита једну инт прошлост краја нашег меморије блока. 81 00:04:11,000 --> 00:04:13,000 Ако погледамо уназад на излазу Валгринд а, 82 00:04:13,000 --> 00:04:16,000 видимо да Валгринд рекао нам је управо то. 83 00:04:16,000 --> 00:04:19,000 Адреса покушавамо да чита почиње 0 бајтова 84 00:04:19,000 --> 00:04:22,000 прошлост краја блока величине 16 бајтова - 85 00:04:22,000 --> 00:04:25,000 четири 32-битне ИНТС да смо додељени. 86 00:04:25,000 --> 00:04:29,000 То је, адреса смо покушавали да читају почиње на самом крају нашег блока, 87 00:04:29,000 --> 00:04:32,000 баш као што смо видели у нашем лошем принтф позива. 88 00:04:32,000 --> 00:04:36,000 Сада, неважећи цитано можда не изгледа као да је велик посао, 89 00:04:36,000 --> 00:04:39,000 али ако користите те податке да контролише проток вашег програма - 90 00:04:39,000 --> 00:04:42,000 На пример, као део уколико изјава или петља - 91 00:04:42,000 --> 00:04:45,000 онда ствари могу ћутке иде лоше. 92 00:04:45,000 --> 00:04:47,000 Гледајте како могу покренути програм инвалид_реад 93 00:04:47,000 --> 00:04:50,000 и ништа необично дешава. 94 00:04:50,000 --> 00:04:52,000 Страшно, зар не? 95 00:04:52,000 --> 00:04:56,000 >> Сада, хајде да погледамо неке више врста грешака које могу да наилазе у свом коду, 96 00:04:56,000 --> 00:04:59,000 па ћемо видети како Валгринд их открије. 97 00:04:59,000 --> 00:05:01,000 Управо смо видели пример једног инвалид_реад, 98 00:05:01,000 --> 00:05:04,000 па сад хајде да проверимо једну инвалид_врите. 99 00:05:04,000 --> 00:05:09,000 Опет, нема грешке или упозорења у компилацију. 100 00:05:09,000 --> 00:05:12,000 Ок, Валгринд каже да постоје две грешке у овом програму - 101 00:05:12,000 --> 00:05:15,000 и инвалид_врите и инвалид_реад. 102 00:05:15,000 --> 00:05:18,000 Хајде да проверимо ову шифру. 103 00:05:18,000 --> 00:05:21,000 Изгледа као да имамо инстанцу класичног стрлен плус један буг. 104 00:05:21,000 --> 00:05:24,000 Код не маллоц додатни бајт простора 105 00:05:24,000 --> 00:05:26,000 за / 0 карактера, 106 00:05:26,000 --> 00:05:30,000 па кад ул примерак отишао да га напишем на ссубстрлен "цс50 стена!" 107 00:05:30,000 --> 00:05:33,000 писало је 1 бајт прошлост краја нашег блока. 108 00:05:33,000 --> 00:05:36,000 Тхе инвалид_реад долази када правимо наш позив принтф. 109 00:05:36,000 --> 00:05:40,000 Принтф завршава читањем неважећи меморију када се чита / 0 карактер 110 00:05:40,000 --> 00:05:43,000 као што изгледа на крају овог низа Е то је штампа. 111 00:05:43,000 --> 00:05:45,000 Али ништа од тога побегао Валгринд. 112 00:05:45,000 --> 00:05:48,000 Видимо да је ухваћен инвалид_врите као део ул копије 113 00:05:48,000 --> 00:05:51,000 на линији 11 у главни, а инвалид_реад део принтф. 114 00:05:51,000 --> 00:05:54,000 Роцк он, Валгринд. 115 00:05:54,000 --> 00:05:57,000 Опет, ово можда не изгледа као велика ствар. 116 00:05:57,000 --> 00:06:00,000 Можемо покренути овај програм изнова и ван Валгринд 117 00:06:00,000 --> 00:06:03,000 и не видим никакве симптоме грешке. 118 00:06:03,000 --> 00:06:06,000 >> Ипак, хајде да погледамо мало варијација то види 119 00:06:06,000 --> 00:06:09,000 како ствари могу добити заиста лоше. 120 00:06:09,000 --> 00:06:14,000 Дакле, готово, ми смо злоупотребљавају ствари више него само мало у овом коду. 121 00:06:14,000 --> 00:06:17,000 Ми само додељивање простора на гомилу за два жице 122 00:06:17,000 --> 00:06:19,000 дужина цс50 стена, 123 00:06:19,000 --> 00:06:22,000 овај пут, сећајући / 0 карактер. 124 00:06:22,000 --> 00:06:25,000 Али онда бацамо у супер-дугом низу у меморијски блок 125 00:06:25,000 --> 00:06:27,000 да С указује на. 126 00:06:27,000 --> 00:06:30,000 Какав ефекат ће то имати на меморијској блока који Т указује? 127 00:06:30,000 --> 00:06:34,000 Па, ако Т указује на меморију која је само поред С, 128 00:06:34,000 --> 00:06:37,000 долази тек након ње, 129 00:06:37,000 --> 00:06:39,000 онда бисмо писали у делу Т. 130 00:06:39,000 --> 00:06:41,000 Хајде да покренете овај код. 131 00:06:41,000 --> 00:06:43,000 Погледајте шта се догодило. 132 00:06:43,000 --> 00:06:47,000 Жице се налазе у нашим гомилу блокова оба изгледа да је одштампан правилно. 133 00:06:47,000 --> 00:06:49,000 Ништа изгледа погрешно уопште. 134 00:06:49,000 --> 00:06:52,000 Међутим, хајде да се вратимо у наш код и 135 00:06:52,000 --> 00:06:55,000 коментар из линије где смо копирали цс50 стене 136 00:06:55,000 --> 00:06:59,000 у другој меморијској блока, указао од стране Т. 137 00:06:59,000 --> 00:07:02,000 Сада, када смо покренули овај код нас треба 138 00:07:02,000 --> 00:07:06,000 видети само садржај првог меморијског блока одштампати. 139 00:07:06,000 --> 00:07:09,000 Вау, иако нисмо ул копија 140 00:07:09,000 --> 00:07:12,000 било знакова у другој хеап блока, један је указао на по Т, 141 00:07:12,000 --> 00:07:15,000 добијамо отисак напоље. 142 00:07:15,000 --> 00:07:18,000 Заиста, стринг смо пуњена у нашем првом блоку 143 00:07:18,000 --> 00:07:21,000 заузеле прво блок и у другом блоку, 144 00:07:21,000 --> 00:07:23,000 чинећи све изгледа нормално. 145 00:07:23,000 --> 00:07:26,000 Валгринд, међутим, каже нам истиниту причу. 146 00:07:26,000 --> 00:07:28,000 Ту смо. 147 00:07:28,000 --> 00:07:32,000 Сви они неважећи чита и пише. 148 00:07:32,000 --> 00:07:36,000 >> Погледајмо пример друге врсте грешке. 149 00:07:36,000 --> 00:07:39,000 Овде смо нешто прилично несрећни. 150 00:07:39,000 --> 00:07:41,000 Ми зграби простор за интег на гомили, 151 00:07:41,000 --> 00:07:45,000 и ми се покрене инт показивач - п - да укаже на том простору. 152 00:07:45,000 --> 00:07:48,000 Међутим, док је наша показивач иницијализован, 153 00:07:48,000 --> 00:07:52,000 подаци који указују да је то управо год ђубре је у том делу гомиле. 154 00:07:52,000 --> 00:07:55,000 Дакле, када смо учитати да податке у инт, 155 00:07:55,000 --> 00:07:57,000 ми смо технички, покрене, 156 00:07:57,000 --> 00:08:00,000 али ми то урадити са џанк подацима. 157 00:08:00,000 --> 00:08:03,000 Позив да се афирмишу, што је згодно за отклањање грешака макро 158 00:08:03,000 --> 00:08:06,000 дефинисан у пригодно назван тврде библиотеке, 159 00:08:06,000 --> 00:08:09,000 ће прекинути програм и ако је његово стање тест не успе. 160 00:08:09,000 --> 00:08:11,000 То јест, ако сам није 0. 161 00:08:11,000 --> 00:08:14,000 У зависности од тога шта је у хеап простору, истакао по п, 162 00:08:14,000 --> 00:08:18,000 Овај програм може да се понекад ради и не у другим временима. 163 00:08:18,000 --> 00:08:20,000 Ако то ради, само смо посрећило. 164 00:08:20,000 --> 00:08:24,000 Компајлер неће ухватити ову грешку, али Валгринд сигуран вољу. 165 00:08:24,000 --> 00:08:28,000 Ту видимо грешку која произилази из нашег коришћења тог јунк података. 166 00:08:28,000 --> 00:08:32,000 >> Када доделити гомили меморију али не деаллоцате или ослободити га, 167 00:08:32,000 --> 00:08:34,000 која се зове цури. 168 00:08:34,000 --> 00:08:37,000 За малу, краткотрајне програму који покреће и одмах излазе, 169 00:08:37,000 --> 00:08:39,000 цурења су прилично безопасни, 170 00:08:39,000 --> 00:08:42,000 али за пројекат већег обима и / или дуговечност, 171 00:08:42,000 --> 00:08:46,000 чак и мала цурења могу једињење у нешто велики. 172 00:08:46,000 --> 00:08:49,000 За ЦС50, ми очекујемо да 173 00:08:49,000 --> 00:08:51,000 брине ослобађање свих гомиле меморије коју додели, 174 00:08:51,000 --> 00:08:54,000 пошто желимо да градимо вештине да правилно рукује процесом ручног 175 00:08:54,000 --> 00:08:56,000 захтева Ц. 176 00:08:56,000 --> 00:08:59,000 Да бисте то урадили, ваш програм треба да има тачан 177 00:08:59,000 --> 00:09:03,000 један-на-један кореспонденција између маллоц и фрее позиве. 178 00:09:03,000 --> 00:09:06,000 Срећом, Валгринд може да вам помогне са меморијским цурења превише. 179 00:09:06,000 --> 00:09:09,000 Овде је цури програм под називом леак.ц да издвоји 180 00:09:09,000 --> 00:09:13,000 простора на гомили, пише на њега, али га не ослободи. 181 00:09:13,000 --> 00:09:16,000 Ми смо саставити га са Направите и покрените га под валгринд, 182 00:09:16,000 --> 00:09:18,000 и видимо да, иако немамо меморијске грешке, 183 00:09:18,000 --> 00:09:20,000 имамо једну пукотину. 184 00:09:20,000 --> 00:09:23,000 Постоји 16 бајтова дефинитивно изгубљено, 185 00:09:23,000 --> 00:09:27,000 што значи да се показивач тог сећања није био у обиму када је програм изашао. 186 00:09:27,000 --> 00:09:30,000 Сада, Валгринд не дају нам гомилу информација о цурења, 187 00:09:30,000 --> 00:09:35,000 али ако пратимо ову малу напомену да даје доле према дну свог извештаја 188 00:09:35,000 --> 00:09:38,000 да поново покрећете са - цури-цхецк = пуна 189 00:09:38,000 --> 00:09:41,000 да видите све детаље процурио меморије, 190 00:09:41,000 --> 00:09:44,000 ћемо добити више информација. 191 00:09:44,000 --> 00:09:46,000 Сада, у хеап резимеу, 192 00:09:46,000 --> 00:09:50,000 Валгринд нам каже где меморија која је изгубљена је првобитно додељена. 193 00:09:50,000 --> 00:09:52,000 Као што знамо из гледа у изворном коду, 194 00:09:52,000 --> 00:09:55,000 Валгринд нас обавештава да смо процуриле меморију 195 00:09:55,000 --> 00:09:58,000 издвојила са позивом на маллоц на линији 8 од леак.ц 196 00:09:58,000 --> 00:10:00,000 у главном функцији. 197 00:10:00,000 --> 00:10:02,000 Прилично диван. 198 00:10:02,000 --> 00:10:04,000 >> Валгринд категорише цурења помоћу ове услове: 199 00:10:04,000 --> 00:10:07,000 Дефинитивно изгубили - то је гомила издвојено меморија 200 00:10:07,000 --> 00:10:10,000 на којима се програм више нема показивач. 201 00:10:10,000 --> 00:10:14,000 Валгринд зна да сте некада имали показивач, али су пошто је изгубио траг о томе. 202 00:10:14,000 --> 00:10:17,000 Ова меморија је дефинитивно процурела. 203 00:10:17,000 --> 00:10:20,000 Индиректно изгубили - то је гомила издвојено меморија 204 00:10:20,000 --> 00:10:24,000 којима су само показивачи на њега такође су изгубљени. 205 00:10:24,000 --> 00:10:27,000 На пример, ако сте изгубили показивач на први чвор повезану листу, 206 00:10:27,000 --> 00:10:30,000 онда прво сама чвор би се дефинитивно изгубљено, 207 00:10:30,000 --> 00:10:34,000 док је било накнадне чворови ће бити индиректно изгубљена. 208 00:10:34,000 --> 00:10:37,000 Можда је изгубио - то је гомила издвојено меморија 209 00:10:37,000 --> 00:10:41,000 на које Валгринд не можемо бити сигурни да ли је показивач или не. 210 00:10:41,000 --> 00:10:44,000 Ипак доступна је гомила издвојено меморија 211 00:10:44,000 --> 00:10:47,000 на који програм и даље има показивач на излазу, 212 00:10:47,000 --> 00:10:50,000 што обично значи да глобална променљива указује на њега. 213 00:10:50,000 --> 00:10:53,000 Да бисте проверили ових цурења, такође ћете морати да укључите опцију 214 00:10:53,000 --> 00:10:55,000 - Још увек доступан = иес 215 00:10:55,000 --> 00:10:58,000 у призивањем Валгринд. 216 00:10:58,000 --> 00:11:01,000 >> Ови различити предмети могу захтевати различите стратегије за њихово чишћење, 217 00:11:01,000 --> 00:11:05,000 али цури треба елиминисати. 218 00:11:05,000 --> 00:11:08,000 Нажалост, фиксирање цурење може бити тешко да уради, 219 00:11:08,000 --> 00:11:11,000 Од погрешних позива на бесплатно да дигне свој програм. 220 00:11:11,000 --> 00:11:14,000 На пример, ако гледамо инвалид_фрее.ц, 221 00:11:14,000 --> 00:11:18,000 видимо пример лошег меморијског Деалокација. 222 00:11:18,000 --> 00:11:21,000 Шта би требало да буде један позив да ослободи цео блок 223 00:11:21,000 --> 00:11:24,000 меморије указао на које инт_блоцк, 224 00:11:24,000 --> 00:11:27,000 уместо тога постао покушај да се ослободи сваког инт величине одељак 225 00:11:27,000 --> 00:11:29,000 сећања појединачно. 226 00:11:29,000 --> 00:11:32,000 Ово ће катастрофално пропасти. 227 00:11:32,000 --> 00:11:34,000 Бум! Шта грешка. 228 00:11:34,000 --> 00:11:36,000 Ово дефинитивно није добро. 229 00:11:36,000 --> 00:11:39,000 Ако сте заглављени са овом врстом грешке, ипак, и не знате где да погледате, 230 00:11:39,000 --> 00:11:41,000 пада назад на нови најбољи пријатељ. 231 00:11:41,000 --> 00:11:44,000 Погодили сте - Валгринд. 232 00:11:44,000 --> 00:11:47,000 Валгринд, као и увек, тачно зна шта је горе. 233 00:11:47,000 --> 00:11:50,000 У аллоц и слободно тачке не подударају. 234 00:11:50,000 --> 00:11:52,000 Имамо 1 аллоц и 4 ослобађа. 235 00:11:52,000 --> 00:11:55,000 И Валгринд нам такође говори где први лоше бесплатан позив - 236 00:11:55,000 --> 00:11:58,000 онај који је покренуло Бловуп - долази од - 237 00:11:58,000 --> 00:12:00,000 линија 16. 238 00:12:00,000 --> 00:12:03,000 Као што видите, лоше позиви на слободне су заиста лоши, 239 00:12:03,000 --> 00:12:05,000 па препоручујемо да пустите да вам програм цурење 240 00:12:05,000 --> 00:12:08,000 док радите на томе функционалност исправна. 241 00:12:08,000 --> 00:12:12,000 Почетак у потрази за цурење тек након ваш програм ради исправно, 242 00:12:12,000 --> 00:12:14,000 без икаквих других грешака. 243 00:12:14,000 --> 00:12:16,000 >> И то је све што имамо за овај видео. 244 00:12:16,000 --> 00:12:18,000 Сада шта чекате? 245 00:12:18,000 --> 00:12:21,000 Иди покренути Валгринд на вашим програмима сада. 246 00:12:21,000 --> 00:12:25,000 Моје име је Нејт Хардисон. Ово је ЦС50. [ЦС50.ТВ]