Кажется, что большинство людей считают отладку искусством, а не наукой. Для тех, кто рассматривает это как науку, а не искусство - какой процесс (ы) вы обычно используете, когда сталкиваетесь с новой проблемой / ошибкой / проблемой?
В общих чертах, то, что я делаю, это:
Попробуйте изолировать проблему. Подумайте, что изменилось, когда ошибка появилась впервые. Над чем ты работаешь? Какую часть кода вы меняли? 99% моих ошибок решаются таким образом. Обычно это что-то глупое.
Если я угадаю, в чем проблема, внимательно посмотрите на код, который, кажется, является причиной. Прочитайте это. Прочитайте это вслух даже. Спросите себя: «Чего я пытаюсь достичь?». Для некоторых типов проблем: Может ли это иметь некоторые побочные эффекты или на него может повлиять код в каком-то другом месте, о котором я даже не думал?
Попробуйте различными способами проанализировать, что идет не так, где и когда (см. Ниже).
Если я до сих пор не имею понятия, я проверяю, есть ли такая же проблема в более старой версии моего источника, попробуйте найти, когда на моей временной шкале проблема появилась впервые. Для этого вам нужно работать с хорошей системой контроля версий, такой как git (в git есть функция bisect, предназначенная именно для такого рода отладки).
Если до сих пор нет подсказки, сделайте перерыв .... это на самом деле часто помогает.
Вернитесь к чертежной доске - рассмотрите, как ваша программа должна работать и имеет ли это смысл.
Это действительно зависит от типа проблемы, но если у меня есть общее представление о том, где может быть проблема, то:
Если я подозреваю, что проблема в некоторой части кода / недавнем изменении, я сначала пытаюсь удалить / закомментировать / изменить или что-то еще, чтобы ошибка исчезла, упростив код, а затем вернуть проблемный код и взять хорошо посмотри на это.
Запустите отладчик с точками останова (если вообще возможно) и посмотрите, как выглядят мои данные, пытаясь найти, когда они начинают плохо себя вести, чтобы лучше понять, где что-то идет не так.
bzr qdiff
команды.Я пытаюсь использовать разработку через тестирование ( TDD ). Я пишу тест, который повторяет ошибку, а затем пытаюсь пройти тест. Иногда сам процесс написания теста помогает найти ошибку.
Это удерживает меня от отладчика большую часть времени и предоставляет регрессионные тесты для предотвращения повторного появления ошибки.
Некоторые ссылки:
источник
Существует несколько определений слова «наука», но, похоже, вы имеете в виду то, что можно более точно назвать « научным методом ». Научный метод может быть обобщен как наблюдение за некоторыми явлениями (предположительно ошибка или неожиданное поведение программы), формулировка гипотезы или гипотезы для объяснения поведения и наиболее вероятные эксперименты, чтобы доказать это (написание теста, который надежно воспроизводит проблему).
Типы ошибок (явлений), которые могут возникнуть, практически бесконечны, а некоторые не обязательно требуют четко определенного процесса. Например, иногда вы наблюдаете ошибку и сразу узнаете, что ее вызвало, просто потому, что вы хорошо знакомы с кодом. В других случаях вы знаете, что при некотором вводе (действие, последовательность шагов и т. Д.) Получается неверный результат (сбой, неверный вывод и т. Д.). Для этих случаев это часто не требует большого "научного" мышления. Некоторая мысль может помочь уменьшить пространство поиска, но распространенный метод - просто пройтись по коду в отладчике и посмотреть, где все пошло не так.
Ситуации, которые я нахожу наиболее интересными и, возможно, достойными научного процесса, - это когда вам вручают какой-то конечный результат и просят объяснить, как это произошло. Очевидным примером этого является аварийный дамп. Вы можете загрузить аварийный дамп и наблюдать за состоянием системы, и ваша задача - объяснить, как она попала в это состояние. В аварийном дампе (или ядре) может отображаться исключительная ситуация, взаимоблокировка, внутренняя ошибка или некоторое «нежелательное» состояние, определенное пользователем (например, медлительность). В этих ситуациях я обычно выполняю следующие шаги:
Узкое наблюдение . Изучите информацию, непосредственно касающуюся конкретной проблемы, если применимо. Очевидными вещами здесь являются стек вызовов, локальные переменные, если вы их видите, строки кода, окружающие проблему. Этот тип исследования конкретного места не всегда применим. Например, изучение «медленной» системы может не иметь очевидного начального местоположения, подобного этому, но ситуация сбоя или внутренней ошибки, вероятно, будет иметь непосредственный и очевидный интерес. Одним конкретным шагом здесь может быть использование таких инструментов, как windbg (запустите! Анализ -v в загруженном аварийном дампе и посмотрите, что он говорит вам).
Широкое наблюдение : изучите другие части системы. Изучите состояние всех потоков в системе, просмотрите любую глобальную информацию (количество пользователей / операций / элементов, активных транзакций / процессов / виджетов и т. Д.), Информацию о системе (ОС) и т. Д. Если пользователь предоставил какие-либо внешние данные Подумайте о тех, с кем вы наблюдали. Например, если вам сказали, что проблема возникает каждый вторник во второй половине дня, спросите себя, что это может означать.
строить гипотезуЭто действительно забавная часть (и я не буду шутить о том, что это весело). Это часто требует большого логического мышления в обратном направлении. Может быть очень приятно думать о том, как система попала в текущее состояние. Я подозреваю, что это та часть, которую многие люди считают искусством. И я полагаю, что это может быть, если программист просто начинает случайным образом бросать вещи, чтобы увидеть, что прилипает. Но с опытом, это может быть довольно четко определенный процесс. Если вы мыслите очень логично на этом этапе, часто можно определить возможные наборы путей, которые привели к данному состоянию. Я знаю, что мы находимся в состоянии S5. Чтобы это произошло, должен был появиться S4a или S4b и, может быть, S3 до S4a и т. Д. Чаще всего этого не может быть несколько элементов, которые могут привести к данному состоянию. Иногда это может помочь записать на блокноте простую диаграмму потока или состояний или серию связанных со временем шагов. Фактические процессы здесь будут сильно различаться в зависимости от ситуации, но серьезное обдумывание (и повторное рассмотрение на предыдущих этапах) в настоящее время часто дают один или несколько правдоподобных ответов. Также обратите внимание, что чрезвычайно важной частью этого шага является устранение невозможного. Удаление невозможного может помочь обрезать пространство решения (помните, что сказал Шерлок Холмс о том, что осталось после того, как вы устранили невозможное). Также обратите внимание, что чрезвычайно важной частью этого шага является устранение невозможного. Удаление невозможного может помочь обрезать пространство решения (помните, что сказал Шерлок Холмс о том, что осталось после того, как вы устранили невозможное). Также обратите внимание, что чрезвычайно важной частью этого шага является устранение невозможного. Удаление невозможного может помочь обрезать пространство решения (помните, что сказал Шерлок Холмс о том, что осталось после того, как вы устранили невозможное).
Эксперимент . На этом этапе попытайтесь воспроизвести проблему, основываясь на гипотезах, полученных на предыдущем этапе. Если вы серьезно подумали на предыдущем шаге, это должно быть очень просто. Иногда я "обманываю" и изменяю кодовую базу, чтобы помочь в данном тесте. Например, недавно я расследовал аварию, которая, как я пришел к выводу, была связана с состоянием гонки. Чтобы проверить это, я просто помещаю Sleep (500) между парой строк кода, чтобы позволить другому потоку делать свои плохие вещи в «правильное» время. Я не знаю, допускается ли это в «реальной» науке, но это совершенно разумно в коде, которым вы владеете.
Если вам удастся воспроизвести его, скорее всего, вы почти закончили (все, что осталось, это простой шаг исправления ... но это на другой день). Обязательно проверьте новый тест в системе регрессионного тестирования. И я должен отметить, что я намеревался сделать это предыдущее заявление о том, что это просто быть насмешкой. Нахождение решения и его реализация могут потребовать большой работы. По моему мнению, исправление ошибки - это не часть процесса отладки, а скорее разработка. И если исправление вообще вовлечено, то это должно потребовать некоторого количества дизайна и обзора.
источник
Попробуйте уменьшить контрольный пример. Когда он достаточно мал, обычно легче найти соответствующий код, который вызывает проблему.
Вполне вероятно, что новая регистрация вызывает проблему, и предыдущая ежедневная сборка прошла нормально. В этом случае ваш журнал изменений из системы контроля версий должен помочь вам решить, кого отлавливать.
Кроме того, если вы знакомы с C / C ++, попробуйте запустить valgrind или очистить, чтобы изолировать проблемы, связанные с памятью.
источник
Самая сложная часть отладки - это изоляция проблемы, особенно когда проблема скрыта под несколькими уровнями. В колледже я изучал музыкальную запись, и, как ни странно, был класс Studio Electronics, который непосредственно здесь применяется. Я собираюсь использовать отладку среды студии как иллюстрацию систематического процесса отладки.
Отладка кода на самом деле не так уж отличается. Отладка намного проще, когда код вызывает исключение. Вы можете проследить назад от трассировки стека этого исключения и установить точки останова на ключевых позициях. Обычно сразу после установки переменной или в строке, которая вызывает метод, который выдает исключение. Вы можете обнаружить, что одно или несколько значений неверны. Если это не правильно (ноль, когда не должно быть, или значение выходит за пределы диапазона), то это процесс обнаружения, почему это не правильно. Точки останова в IDE эквивалентны электронным контрольным точкам (предназначенным для измерительного щупа для проверки цепи).
Теперь, после того, как я прошел через эту сложную часть выяснения, где моя настоящая проблема, я напишу несколько юнит-тестов, чтобы проверить это в будущем.
источник
Из-за неприятных ошибок, которые я изо всех сил стараюсь выследить поздно вечером, моя самая эффективная стратегия - встать и уйти на несколько минут. Обычно новые идеи о возможных источниках ошибок начинают поступать уже через 30 секунд.
источник
Для более практического подхода:
Если ошибка связана с необработанным исключением - посмотрите трассировку стека. Нулевая ссылка, индекс за пределами границ и т. Д., А также ваши собственные определенные исключения являются наиболее распространенными, вы можете назначить эту ошибку для младшего разработчика, это, вероятно, легко и хороший учебный опыт.
Если это происходит не на каждой машине, это, вероятно, форма проблемы гонки / многопоточности. Это очень весело, чтобы выследить, поставить вашего скучного старшего программиста на это. Много регистрации, хорошие знания и хорошие инструменты делают это.
Еще один большой класс ошибок - это когда группе тестирования или клиенту (-ам) не нравится определенное поведение. Например, им не нравится, что вы решаете отображать идентификаторы пользователей или что при поиске вы не получаете автозаполнение. Это подлинные ошибки, подумайте о лучшем управлении продуктом и разработчиками с более широким обзором. Разработчику должно потребоваться относительно короткое время, чтобы «исправить» это, если он строит систему с учетом расширения.
80% всех других ошибок устраняются при наличии хороших систем регистрации и сбора достаточного количества информации для их устранения. Используйте встроенную трассировку с несколькими уровнями сложных систем журналирования, таких как Log4Net / Log4J
Ошибки производительности - это отдельная категория, правило golder здесь «измеряй сначала, исправляй позже!», и вы будете удивлены, увидев, сколько разработчиков просто догадаются, где проблема, и сразу же решите ее, только чтобы увидеть позже просто на 3-4% уменьшение времени отклика.
источник
У меня есть два подхода:
Divide and Conquer
парадигме.Эти подходы помогли мне большую часть времени.
источник