Отладка и бинарный поиск

«Жемчужины программирования» в столбце 2 («АГА! Алгоритм») рассказывает о том, как бинарный поиск помогает в различных процессах, таких как сортировка, обход дерева. Но в нем упоминается, что бинарный поиск можно использовать при «отладке программы». Может кто-нибудь объяснить, как это делается?


person unj2    schedule 09.05.2009    source источник


Ответы (7)


Другая возможность заключается в том, что у вас есть ошибка, и вы знаете, что ее не было в вашем февральском выпуске, но она была в вашем апрельском выпуске (или, скорее, в вашем кандидате в апрельском выпуске — на самом деле вы бы никогда не отправить ошибку своим пользователям, не так ли?).

Вы можете выполнить ручной бинарный поиск по истории контроля версий, чтобы сузить круг, когда была обнаружена ошибка. Сначала проверьте код на полпути между двумя выпусками, соберите его и посмотрите, есть ли ошибка. Продолжайте разбиение, пока не узнаете, когда оно было введено. Если вы не знаете, с чего начать поиск ошибки, это может быть очень эффективным, особенно если вы делаете достаточно небольшие коммиты.

Это очень хорошо работает с Subversion, потому что у него есть номера ревизий для всего репозитория. Если ваш февральский выпуск был версии 533, а ваш апрельский выпуск был версии 701, вы обновитесь до версии 617, протестируете ее и продолжите. (На самом деле, я обычно округляю до 600, чтобы мне не приходилось столько заниматься математикой в ​​голове.) Как только я начинаю сужать круг, я начинаю смотреть комментарии к коммиту и делать обоснованные предположения («Я действительно не думаю, что эта фиксация сломала бы его"), поэтому мне обычно не нужно выполнять все проверки log2(n).

Я никогда не использовал Git, но они сделали еще один шаг вперед благодаря встроенному "bisect. Вы указываете ему начальную точку (когда стало известно, что он работает?) и конечную точку (когда вы заметили, что он сломан?), и он автоматически получит код промежуточной точки бинарного поиска. Затем, после того, как вы построили и протестировали, вы сообщаете, прошла ли эта версия или нет; затем он получает код следующей промежуточной точки. Вы даже можете сказать ему запускать команду для каждой версии и использовать код выхода команды, чтобы определить, является ли версия пройденной или неудачной, и в этот момент она может работать в полностью автоматическом режиме.

person Joe White    schedule 09.05.2009
comment
Я никогда не использовал Git — пожалуйста, скажите мне, что это изменилось (или что вы, по крайней мере, пробовали другую распределенную систему VC, может быть, Mercurial) с 2009 года! Это намного приятнее. - person Kyle Strand; 22.12.2015
comment
@KyleStrand Да, сейчас я использую Git. :-) - person Joe White; 22.12.2015

Если вы не знаете, какая строка в 100-строчной программе ошибочна, попробуйте запустить первые 50 строк и пропустить остальные. Если проблема появится, вы узнаете, что этот первый сегмент содержит ошибку. Затем вы попытаетесь разделить это и запустить первые 25 строк и посмотреть, есть ли проблема, и так далее, пока вы не найдете достаточно короткий фрагмент для просмотра.

Идея бинарного поиска состоит в том, чтобы идентифицировать/изолировать небольшую область, в которой есть ошибки. Однако, как и все методы, это применимо не во всех ситуациях. Например: рекурсивная функция будет ужасно громоздкой для такого инструмента. Когда путей выполнения слишком много, сегментация исполняемого кода может стать затруднительной.

person dirkgently    schedule 09.05.2009
comment
о, так что бинарный поиск здесь не означает, что вы ищете элементы, а просто делите программу и ищете проблему. Спасибо. - person unj2; 10.05.2009

Двоичный поиск – это эффективный способ найти элемент в отсортированном списке. Например, если вы ищете определенную страницу в книге (скажем, стр. 147), вы должны открыть книгу ближе к середине и определить, находится ли открытая страница до или после страницы, которую вы ищете. Затем вы выберете раздел, до которого сузили его, и повторите процесс: разделите его пополам и определите, какая половина содержит страницу 147. Еще лучше, вы можете угадать, как далеко на странице 147 находится недалеко, если книга очень длинная. и ближе к концу короткой книги и используйте это предположение в качестве первого пункта деления. Этот вариант бинарного поиска называется интерполяционным поиском.

Поэтому, если у вас есть ошибка и отсортированный список, в котором она может скрываться, поиск с интерполяцией обычно является способом ее устранения. Другие ответы объясняют распространенные случаи ошибки, скрытой где-то в диапазоне строк или коммитов исходного кода. Но методику можно применять и в других ситуациях:

  • поиск в журнале

    В системе с длительным сроком службы, особенно в той, которая обрабатывает так много данных, что вам приходится ежедневно менять свои журналы, нередко можно увидеть, что что-то сломано сегодня, что было нормально несколько недель/месяцев/лет назад. В сложной взаимосвязанной системе возможно обнаружение ошибок без каких-либо изменений кода. Найти, что изменилось в оборудовании, сети, ОС, конфигурации (хотя это должно храниться вместе с кодом), вводе, ручных процедурах и т. д. может быть сложно, поскольку многие из этих вещей меняются в течение длительного времени. периоды времени. Полнотекстовый поиск журналов (будь то в таблице или в файлах) часто нецелесообразен.

    В этом случае практически нет другого выбора, кроме как открыть журналы где-то посередине и посмотреть, существует ли проблема или нет. Затем вырежьте участок, где, как вы знаете, прячется ошибка, и снова найдите ошибку. В конце концов, вы сможете обнаружить первый момент появления вашей ошибки, что значительно облегчит поиск виновника.

  • введите поиск

    На днях я заметил непонятная "ошибка" с длинным текстом. Самый быстрый способ отследить точную границу между текстом, который работает, и текстом, который ломает систему, — это разрезать текст пополам, пока я не найду разделительную линию. (Оказывается я идиот, но у меня получилось лучше подсчет бананов.)

  • этапы концептуального процесса

    Большинство людей даже не знают, что большую часть времени они используют бинарный (или, лучше, интерполяционный) поиск; это действительно естественный способ решить проблему. Думая о длинной последовательности шагов, которая может содержать потенциальную ошибку, часто имеет смысл сначала проверить вывод одного из промежуточных шагов, чтобы избежать проверки всего кода только для того, чтобы обнаружить проблему на последнем шаге.

person Jon Ericson    schedule 31.08.2015
comment
конечно, чтобы быть эффективным для отсортированного списка, этот список должен иметь доступ O (1). Связанные списки, например, этого не делают. -- re input search Я часто ищу конкретное изменение в истории страниц Википедии таким образом. - person Will Ness; 18.12.2015
comment
@WillNess Вы все еще можете иметь эффективный двоичный поиск без доступа O(1). Списки пропуска, двоичные кучи и т. д. Можно использовать для организации данных, чтобы получить почти те же характеристики поиска, что и в плоском массиве, с лучшими характеристиками для вставки/удаления. - person Richard J. Ross III; 19.12.2015
comment
@RichardJ.RossIII Недостатком всех них является то, что они обычно сопровождаются отсутствием местности. Не всегда; вы можете использовать большую страницу с ручным разделением, чтобы память не сбивалась. На современных процессорах локальность кеша (и предсказуемость доступа) может дать смехотворно огромный (в 100 раз) прирост производительности. - person Yakk - Adam Nevraumont; 21.12.2015
comment
Я также иногда использую ручной бинарный поиск как последнюю попытку найти проблемную строку кода. Я комментирую примерно половину своего кода, сохраняя при этом его работоспособность. Если ошибка все еще существует, я комментирую половину оставшегося кода. Если ошибка исчезнет, ​​я раскомментирую половину ранее прокомментированного кода. Промойте, повторяйте, пока не будет найден оскорбительный код. Это, конечно, не первый инструмент, который я использую, но время от времени мне приходится прибегать к нему. ⛵???? - person Jeff B; 23.12.2015
comment
+1 к части «концептуальных шагов процесса» — это естественный процесс, который мы используем и в нашей повседневной жизни, даже не осознавая и не понимая, что мы это делаем. - person Ron.B.I; 24.12.2015

Двоичный поиск может помочь в отладке следующими способами:

  1. Предположим, контроль должен достичь определенной точки, а вы подозреваете, что этого не происходит. Поместите операторы печати в первую и последнюю строки кода. Предположим, вы видите результат первого, но не второго оператора. Поместите оператор печати в середине и повторите попытку. Таким образом, вы используете бинарный поиск по пространству строк кода, чтобы найти ошибку.
  2. Предположим, вы используете систему контроля версий. Версия 10 прошла все тесты. Готовящаяся к выпуску версия 70 не проходит некоторые тесты. Проверьте версию 40 и проведите на ней тесты. Если она работает нормально, попробуйте версию 55. Если версия 40 не работает, попробуйте версию 25. Таким образом, вы используете двоичный поиск по пространству версий программы, чтобы обнулить первую версию, в которой в программу попала ошибка.
person Yuval F    schedule 09.05.2009

Допустим, у вас есть ошибка, но вы не знаете, где она. Вы можете размещать точки останова случайным образом или пошагово в коде, проверяя данные на каждой остановке. Однако лучшей стратегией было бы выбрать место в середине блока кода, на который вы смотрите. Если проблема существует там, выберите точку посередине между начальной и текущей точкой и повторите попытку. Если проблема не существует, выберите место посередине между текущим местом и концом и повторите попытку. Продолжайте в том же духе, пока не сократите объем кода до блока, достаточно большого для выполнения одного шага более эффективно, чем остановка/перезапуск. Это в основном делает двоичный поиск в вашем коде.

person tvanfosson    schedule 09.05.2009

Полный алгоритм называется Delta Debugging и был разработан Андреасом Зеллером, профессором информатики и автором книги Почему программы не работают.

Однако это не только бинарный поиск. Бинарный поиск выполняется только в начале, и как только бинарный поиск больше не минимизирует входные данные, используется другой подход.

Полный алгоритм не так уж сложен для понимания, на самом деле он очень прост. Однако иногда бывает сложно воспроизвести ошибку и применить решение независимо от того, была ли проблема воспроизведена.

Помимо книги, есть бесплатный онлайн-курс по Udacity. Если вы предпочитаете короткую версию, прочтите его документ IEEE< /а>

person Thomas Weller    schedule 31.08.2015

вы можете закомментировать код, добавить комментарий к журналу или просто установить точку останова

отлично подходит для кода без ошибок, но с неработающей функцией, и вы полны сомнений в себе

Сначала установите точку останова прямо в середине кода, если все в порядке, значит проблема не в нем.

затем установите его на 75% кодовой точки - если проблема возникает здесь, вы знаете, что она находится в коде между 50% и 75%

Затем вы устанавливаете его на 57%

Опять же, если проблема есть, вы снова делите ее пополам.

По сути, вы можете найти проблему за несколько минут, а не тратить интеллектуальные часы на повторный анализ кода.

Тогда все еще зависит от вас, чтобы исправить это.

person Gareth Thomas    schedule 09.08.2015