Как можно искать логическую ошибку в программе
Закладки на сайте Проследить за страницей | Created 1996-2023 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |
Синтаксические и логические ошибки при выполнении программы
Синтаксические и логические ошибки при выполнении программы. Основные средства отладки можно получить через меню Debug (Отладить) и панель инструментов, вызвать которую можно командами View (Вид) Toolbars (Панели инструментов) -» Debug (рис. 3.14). Вкладки панели следующие:
- • Start (запуск программы);
- • Pause (приостановка программы);
- • End (останов программы);
- • Toggle Breakpoint (включить/выключить контрольную точку);
- • Step Into (пошаговая обработка с заходом в процедуры);
- • Step Over (пошаговая обработка без захода в процедуры);
- • Step Out (выход из процедуры);
- • Locals Window (включить/выключить локальное окно);
- • Immediate Window (окно непосредственного выполнения);
- • Watch Window (включить/выключить окно наблюдаемых переменных);
Рис. 3.14. Отладка программы
- • Quick Watch (быстрый просмотр значения переменной);
- • Call Stack (просмотр списка вызова процедур).
Для просмотра списка возможного выявления ошибок следует открыть меню Tools (Сервис) и выбрать пункт Options (Параметры). На экране появится окно, где следует установить флажки. Чтобы работа не прерывалась сообщениями о каждой ошибке, нужно снять флажок Auto Syntax Check (Автоматическая проверка синтаксиса).
Среда разработки Visual Basic обнаруживает ошибки типов или неполные программные блоки. Visual Basic допускает выполнение программы с необъявленными переменными. Оператор Option Explicit (раздел General или модуль) определяет необъявленные переменные.
Если компилятор обнаружит ошибки, то для их исправления и продолжения работы достаточно:
- • изменить подсвеченную строку и нажать клавишу F5 или выбрать команды Run —» Continue;
- • изменить программу и запустить ее снова командами Run —» Restart (или нажать сочетание клавиш Shift+F5);
- • запустить программу с другого места, щелкнув мышью по другой строке и выбрав в меню Debug команду Set Next Statement, и нажать F1.
Завершить программу можно командой End в меню Run.
Точка останова (контрольная точка) — строка, где прерывается выполнение программы (выделяется красным цветом). Запущенная программа прервется на этой строке, строка будет выделена желтым цветом и стрелкой.
Способы создания точек останова:
- • щелчком мыши на нужной строке и нажатием клавиши F9;
- • выбрав в меню Debug команду Toggle Breakpoint (Установить точку останова);
- • на панели Debug щелкнуть по кнопке Toggle Breakpoint.
Отмена точек останова выполняется с помощью команд
Debug —» Clear All Breakpoints (Убрать все точки останова).
Порядок наблюдения за поведением требуемой переменной:
- • установить точку останова в строке, где есть наблюдаемая переменная;
- • запустить программу (клавиша F5 или команда Start);
- • задержать указатель мыши над переменной, появится окно с ее текущим значением.
Порядок наблюдения нескольких переменных с помощью окна Watches (Наблюдаемые переменные):
- • установить точки останова в строках кода, где есть наблюдаемые переменные;
- • запустить программу;
- • в точке останова подсветить переменную, добавляемую к списку просматриваемых значений;
- • щелчком правой кнопки мыши вызвать контекстное меню и в нем выбрать команду Add Watch (Добавить наблюдаемую переменную);
- • в диалоговом окне Add Watch выбрать имя переменной (Expression), область видимости переменной (Context), тип наблюдения (Watch Туре) и др., нажать кнопку ОК;
- • для отображения окна Watches следует выбрать в меню View команду Watch Window (Окно наблюдения).
Пошаговую (построчную) проверку выполнения программы можно провести в одном из двух режимов:
- • Step Into (пошаговая обработка с заходом в процедуры) — выполняются все строки программы, включая строки процедур;
- • Step Over (пошаговая обработка без захода в процедуры) — вызываемые процедуры выполняются как один оператор, а затем — очередная строка программы.
Используя панель Debug, при отладке следует выполнить следующее:
- • открыть отлаживаемый проект;
- • вызвать панель Debug;
- • панель Debug перетащить на форму (для удобства — вниз);
- • запустить проект, нажав кнопку Start;
- • если выдаваемые результаты неверны, следует щелкнуть по кнопке Break (Останов) — программа остановится, а в появившемся окне Code будет показан текст выполнения программы;
- • щелчком по кнопке Step Into можно открыть инструкцию, чтобы выполнить следующий оператор;
- • для запуска приложения нужно в форме нажать кнопку, например Command 1, в окне Code отобразится процедура обработки прерывания Commandl_Click, первый оператор которой будет выделен желтым цветом;
- • при щелчке по кнопке Step Into будет выполнен оператор Sub, а следующий оператор будет выделен; если в этом операторе есть проверяемая переменная, то ее нужно поместить в окно Watches;
- • выделить проверяемую переменную и щелкнуть по кнопке Quick Watch (Быстрый просмотр переменных). Появится диалоговое окно, в котором будут содержаться имя переменной, ее значение, тип, назначение;
- • при щелчке в диалоговом окне Quick Watch в нижней части экрана появится окно Watches, где будет отображена выбранная переменная. В это окно можно поместить другие переменные;
- • далее щелкнуть по кнопке Step Into для выполнения следующего оператора и т. д. Таким образом, наблюдая значения переменных в окне Watches, можно определить логику программы и обнаружить ошибки.
При пошаговой отладке можно воспользоваться также оператором Stop, поместив его в нужное место. Выполнение программы по достижении Stop будет приостановлено. В режиме останова можно использовать окно Code и панель инструментов Debug.
Поиск и исправление логических ошибок в программе или коде HTML
Поиск и исправление ошибок в программе — это интересная и необычная задача. Некоторые ошибки найти и исправить несложно. А для других до сих пор конкретных алгоритмов не придумали, поэтому приходится ограничиться лишь обобщенными решениями, следовани е которым облегчит ваш поиск и сделает вашу программу функциональной и эффективной.
Поиск и исправление ошибок в программе
- Синтаксические — ошибки, которые допускаются в результате невнимательности программистов: неправильно выбран оператор, пропущена буква или символ, лишние буква, символ, оператор и т. п.
- Логические — ошибки, которые возникают от неправильного выполнения скрипта или части кода. Такие ошибки могут привести к критическим ситуациям, когда становится невозможн ой дальнейшая работа или модернизация программы. Как правило, эта категория ошибок очень трудно обнаруживается.
Синтаксические ошибки
- н аходите нужный валидатор,
- находите при помощи него синтаксические ошибки,
- исправляете ошибки.
Логические ошибки
- Всегда записывайте ошибку в блокнот или трекер. Как только заметили логическую ошибку в программе, нужно записать ее в трекер. Потому что вы не знаете , сколько уйдет времени и сил на поиск такой ошибки. А в процессе поиска может произойти все что угодно и вы просто можете забыть какие-то важные детали о самой ошибке.
- «Ок, Google!». Если вы нашли ошибку, то есть шанс, что она не уникальна и кто-то с ней уже сталкивался. А это значит, что вполне вероятно, что у кого-то уже есть решение этой проблемы. Поэтому попробуйте найти ее решение в сети.
- Ищите строку! Если поиск в сети не дал результатов, то запустите программу в отладчике и попробуйте найти строку кода, где возникает ошибка. Это , скорее всего , не решит проблему, но даст вам хоть какое-то представление о ней и позволит продолжить дальнейшие поиски.
- Найдите точную строку! Отладчик вам выдаст строку с багом, но , скорее всего , причина будет не в этой строке. Чаще всего причина возникает в данных, которые получила эта строка с багом. Поэтому нужно провести более тщательный анализ и найти причину и природу возникновения ошибки. Ошибки могут происходить по-разным причинам, поэтому это т процесс будет не самым простым и легким.
- Исключайте. Может так случиться, что сразу найти нужную строку кода не получится. В таком случае нужно выявить «проблемный» блок кода. Для этого нужно постепенно отключать компоненты программы, пока не будет выявлен «проблемный» компонент.
- Нужно исключить проблему в аппаратном обеспечении. Редкий случай, но бывает так, что проблема с «железом» вызывает ошибки с исследуемой программой. Можно обновить операционную систему, среду разработк и , заменить оперативную память и т. д.
- Ищите совпадения. Когда возникают ошибки в программе? В одно и то же время? В одном и том же месте? Что обще го у пользователей, у которых возника ю т ошибки? Задавайте подобные вопросы и ищите взаимосвязь. Это м ожет натолкнуть вас на поиск самой проблемы.
- Обратитесь за помощью. Не стесняйтесь спрашивать у более опытных коллег, что может быть не так с вашей программой? Как найти ошибки в ко д е и как их исправить? Ведь проблема может быть в чем угодно, а поиски решения могут занять долгое время. А с вами рядом всегда могут оказаться те, к то сможет помочь.
Заключение
Поиск и исправление логических ошибок в программе иногда становится очень стрессовой задачей. Поэтому в первую очередь никогда не нужно паниковать, если ваша программа работает не так , как надо. Не нужно сразу обвинять всех подряд или себя в том , что такая ошибка возникла.
Иногда логические ошибки действительно возникают по стечению обстоятельств и чисто случайно, поэтому только ваш и спокойствие и размеренность помо гут их обнаружить.
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.
Как искать и исправлять ошибки в коде
У начинающих программистов поиск и устранение ошибок (багов — от англ. bug) занимает очень много времени. В этой статье предложена пошаговая инструкция, которая поможет найти и устранить ошибки.
Искать ошибки в программах — непростая задача. Здесь нет никаких готовых методик или рецептов успеха. Можно даже сказать, что это — искусство. Тем не менее есть общие советы, которые помогут вам при поиске. В статье описаны основные шаги, которые стоит предпринять, если ваша программа работает некорректно.
Шаг 1: Занесите ошибку в трекер
После выполнения всех описанных ниже шагов может так случиться, что вы будете рвать на себе волосы от безысходности, все еще сидя на работе, когда поймете, что:
- Вы забыли какую-то важную деталь об ошибке, например, в чем она заключалась.
- Вы могли делегировать ее кому-то более опытному.
Трекер поможет вам не потерять нить размышлений и о текущей проблеме, и о той, которую вы временно отложили. А если вы работаете в команде, это поможет делегировать исправление коллеге и держать все обсуждение в одном месте.
Вы должны записать в трекер следующую информацию:
- Что делал пользователь.
- Что он ожидал увидеть.
- Что случилось на самом деле.
Это должно подсказать, как воспроизвести ошибку. Если вы не сможете воспроизвести ее в любое время, ваши шансы исправить ошибку стремятся к нулю.
Шаг 2: Поищите сообщение об ошибке в сети
Если у вас есть сообщение об ошибке, то вам повезло. Или оно будет достаточно информативным, чтобы вы поняли, где и в чем заключается ошибка, или у вас будет готовый запрос для поиска в сети. Не повезло? Тогда переходите к следующему шагу.
Шаг 3: Найдите строку, в которой проявляется ошибка
Если ошибка вызывает падение программы, попробуйте запустить её в IDE под отладчиком и посмотрите, на какой строчке кода она остановится. Совершенно необязательно, что ошибка будет именно в этой строке (см. следующий шаг), но, по крайней мере, это может дать вам информацию о природе бага.
Шаг 4: Найдите точную строку, в которой появилась ошибка
Как только вы найдете строку, в которой проявляется ошибка, вы можете пройти назад по коду, чтобы найти, где она содержится. Иногда это может быть одна и та же строка. Но чаще всего вы обнаружите, что строка, на которой упала программа, ни при чем, а причина ошибки — в неправильных данных, которые появились ранее.
Если вы отслеживаете выполнение программы в отладчике, то вы можете пройтись назад по стектрейсу, чтобы найти ошибку. Если вы находитесь внутри функции, вызванной внутри другой функции, вызванной внутри другой функции, то стектрейс покажет список функций до самой точки входа в программу (функции main() ). Если ошибка случилась где-то в подключаемой библиотеке, предположите, что ошибка все-таки в вашей программе — это случается гораздо чаще. Найдите по стектрейсу, откуда в вашем коде вызывается библиотечная функция, и продолжайте искать.
Шаг 5: Выясните природу ошибки
Ошибки могут проявлять себя по-разному, но большинство из них можно отнести к той или иной категории. Вот наиболее частые.
- Ошибка на единицу
Вы начали цикл for с единицы вместо нуля или наоборот. Или, например, подумали, что метод .count() или .length() вернул индекс последнего элемента. Проверьте документацию к языку, чтобы убедиться, что нумерация массивов начинается с нуля или с единицы. Эта ошибка иногда проявляется в виде исключения Index out of range . - Состояние гонки
Ваш процесс или поток пытается использовать результат выполнения дочернего до того, как тот завершил свою работу. Ищите использование sleep() в коде. Возможно, на мощной машине дочерний поток выполняется за миллисекунду, а на менее производительной системе происходят задержки. Используйте правильные способы синхронизации многопоточного кода: мьютексы, семафоры, события и т. д. - Неправильные настройки или константы
Проверьте ваши конфигурационные файлы и константы. Я однажды потратил ужасные 16 часов, пытаясь понять, почему корзина на сайте с покупками виснет на стадии отправки заказа. Причина оказалась в неправильном значении в /etc/hosts , которое не позволяло приложению найти ip-адрес почтового сервера, что вызывало бесконечный цикл в попытке отправить счет заказчику. - Неожиданный null
Бьюсь об заклад, вы не раз получали ошибку с неинициализированной переменной. Убедитесь, что вы проверяете ссылки на null , особенно при обращении к свойствам по цепочке. Также проверьте случаи, когда возвращаемое из базы данных значение NULL представлено особым типом. - Некорректные входные данные
Вы проверяете вводимые данные? Вы точно не пытаетесь провести арифметические операции с введенными пользователем строками? - Присваивание вместо сравнения
Убедитесь, что вы не написали = вместо == , особенно в C-подобных языках. - Ошибка округления
Это случается, когда вы используете целое вместо Decimal , или float для денежных сумм, или слишком короткое целое (например, пытаетесь записать число большее, чем 2147483647, в 32-битное целое). Кроме того, может случиться так, что ошибка округления проявляется не сразу, а накапливается со временем (т. н. Эффект бабочки). - Переполнение буфера и выход за пределы массива
Проблема номер один в компьютерной безопасности. Вы выделяете память меньшего объема, чем записываемые туда данные. Или пытаетесь обратиться к элементу за пределами массива. - Программисты не умеют считать
Вы используете некорректную формулу. Проверьте, что вы не используете целочисленное деление вместо взятия остатка, или знаете, как перевести рациональную дробь в десятичную и т. д. - Конкатенация строки и числа
Вы ожидаете конкатенации двух строк, но одно из значений — число, и компилятор пытается произвести арифметические вычисления. Попробуйте явно приводить каждое значение к строке. - 33 символа в varchar(32)
Проверяйте данные, передаваемые в INSERT , на совпадение типов. Некоторые БД выбрасывают исключения (как и должны делать), некоторые просто обрезают строку (как MySQL). Недавно я столкнулся с такой ошибкой: программист забыл убрать кавычки из строки перед вставкой в базу данных, и длина строки превысила допустимую как раз на два символа. На поиск бага ушло много времени, потому что заметить две маленькие кавычки было сложно. - Некорректное состояние
Вы пытаетесь выполнить запрос при закрытом соединении или пытаетесь вставить запись в таблицу прежде, чем обновили таблицы, от которых она зависит. - Особенности вашей системы, которых нет у пользователя
Например: в тестовой БД между ID заказа и адресом отношение 1:1, и вы программировали, исходя из этого предположения. Но в работе выясняется, что заказы могут отправляться на один и тот же адрес, и, таким образом, у вас отношение 1:многим.
Если ваша ошибка не похожа на описанные выше, или вы не можете найти строку, в которой она появилась, переходите к следующему шагу.
Шаг 6: Метод исключения
Если вы не можете найти строку с ошибкой, попробуйте или отключать (комментировать) блоки кода до тех пор, пока ошибка не пропадет, или, используя фреймворк для юнит-тестов, изолируйте отдельные методы и вызывайте их с теми же параметрами, что и в реальном коде.
Попробуйте отключать компоненты системы один за другим, пока не найдете минимальную конфигурацию, которая будет работать. Затем подключайте их обратно по одному, пока ошибка не вернется. Таким образом вы вернетесь на шаг 3.
Шаг 7: Логгируйте все подряд и анализируйте журнал
Пройдитесь по каждому модулю или компоненту и добавьте больше сообщений. Начинайте постепенно, по одному модулю. Анализируйте лог до тех пор, пока не проявится неисправность. Если этого не случилось, добавьте еще сообщений.
Ваша задача состоит в том, чтобы вернуться к шагу 3, обнаружив, где проявляется ошибка. Также это именно тот случай, когда стоит использовать сторонние библиотеки для более тщательного логгирования.
Шаг 8: Исключите влияние железа или платформы
Замените оперативную память, жесткие диски, поменяйте сервер или рабочую станцию. Установите обновления, удалите обновления. Если ошибка пропадет, то причиной было железо, ОС или среда. Вы можете по желанию попробовать этот шаг раньше, так как неполадки в железе часто маскируют ошибки в ПО.
Если ваша программа работает по сети, проверьте свитч, замените кабель или запустите программу в другой сети.
Ради интереса, переключите кабель питания в другую розетку или к другому ИБП. Безумно? Почему бы не попробовать?
Если у вас возникает одна и та же ошибка вне зависимости от среды, то она в вашем коде.
Шаг 9: Обратите внимание на совпадения
- Ошибка появляется всегда в одно и то же время? Проверьте задачи, выполняющиеся по расписанию.
- Ошибка всегда проявляется вместе с чем-то еще, насколько абсурдной ни была бы эта связь? Обращайте внимание на каждую деталь. На каждую. Например, проявляется ли ошибка, когда включен кондиционер? Возможно, из-за этого падает напряжение в сети, что вызывает странные эффекты в железе.
- Есть ли что-то общее у пользователей программы, даже не связанное с ПО? Например, географическое положение (так был найден легендарный баг с письмом за 500 миль).
- Ошибка проявляется, когда другой процесс забирает достаточно большое количество памяти или ресурсов процессора? (Я однажды нашел в этом причину раздражающей проблемы «no trusted connection» с SQL-сервером).
Шаг 10: Обратитесь в техподдержку
Наконец, пора попросить помощи у того, кто знает больше, чем вы. Для этого у вас должно быть хотя бы примерное понимание того, где находится ошибка — в железе, базе данных, компиляторе. Прежде чем писать письмо разработчикам, попробуйте задать вопрос на профильном форуме.
Ошибки есть в операционных системах, компиляторах, фреймворках и библиотеках, и ваша программа может быть действительно корректна. Но шансы привлечь внимание разработчика к этим ошибкам невелики, если вы не сможете предоставить подробный алгоритм их воспроизведения. Дружелюбный разработчик может помочь вам в этом, но чаще всего, если проблему сложно воспроизвести вас просто проигнорируют. К сожалению, это значит, что нужно приложить больше усилий при составлении багрепорта.
Полезные советы (когда ничего не помогает)
- Позовите кого-нибудь еще.
Попросите коллегу поискать ошибку вместе с вами. Возможно, он заметит что-то, что вы упустили. Это можно сделать на любом этапе. - Внимательно просмотрите код.
Я часто нахожу ошибку, просто спокойно просматривая код с начала и прокручивая его в голове. - Рассмотрите случаи, когда код работает, и сравните их с неработающими.
Недавно я обнаружил ошибку, заключавшуюся в том, что когда вводимые данные в XML-формате содержали строку xsi:type=’xs:string’ , все ломалось, но если этой строки не было, все работало корректно. Оказалось, что дополнительный атрибут ломал механизм десериализации. - Идите спать.
Не бойтесь идти домой до того, как исправите ошибку. Ваши способности обратно пропорциональны вашей усталости. Вы просто потратите время и измотаете себя. - Сделайте творческий перерыв.
Творческий перерыв — это когда вы отвлекаетесь от задачи и переключаете внимание на другие вещи. Вы, возможно, замечали, что лучшие идеи приходят в голову в душе или по пути домой. Смена контекста иногда помогает. Сходите пообедать, посмотрите фильм, полистайте интернет или займитесь другой проблемой. - Закройте глаза на некоторые симптомы и сообщения и попробуйте сначала.
Некоторые баги могут влиять друг на друга. Драйвер для dial-up соединения в Windows 95 мог сообщать, что канал занят, при том что вы могли отчетливо слышать звук соединяющегося модема. Если вам приходится держать в голове слишком много симптомов, попробуйте сконцентрироваться только на одном. Исправьте или найдите его причину и переходите к следующему. - Поиграйте в доктора Хауса (только без Викодина).
Соберите всех коллег, ходите по кабинету с тростью, пишите симптомы на доске и бросайте язвительные комментарии. Раз это работает в сериалах, почему бы не попробовать?
Что вам точно не поможет
- Паника
Не надо сразу палить из пушки по воробьям. Некоторые менеджеры начинают паниковать и сразу откатываться, перезагружать сервера и т. п. в надежде, что что-нибудь из этого исправит проблему. Это никогда не работает. Кроме того, это создает еще больше хаоса и увеличивает время, необходимое для поиска ошибки. Делайте только один шаг за раз. Изучите результат. Обдумайте его, а затем переходите к следующей гипотезе. - «Хелп, плиииз!»
Когда вы обращаетесь на форум за советом, вы как минимум должны уже выполнить шаг 3. Никто не захочет или не сможет вам помочь, если вы не предоставите подробное описание проблемы, включая информацию об ОС, железе и участок проблемного кода. Создавайте тему только тогда, когда можете все подробно описать, и придумайте информативное название для нее. - Переход на личности
Если вы думаете, что в ошибке виноват кто-то другой, постарайтесь по крайней мере говорить с ним вежливо. Оскорбления, крики и паника не помогут человеку решить проблему. Даже если у вас в команде не в почете демократия, крики и применение грубой силы не заставят исправления магическим образом появиться.
Ошибка, которую я недавно исправил
Это была загадочная проблема с дублирующимися именами генерируемых файлов. Дальнейшая проверка показала, что у файлов различное содержание. Это было странно, поскольку имена файлов включали дату и время создания в формате yyMMddhhmmss . Шаг 9, совпадения: первый файл был создан в полпятого утра, дубликат генерировался в полпятого вечера того же дня. Совпадение? Нет, поскольку hh в строке формата — это 12-часовой формат времени. Вот оно что! Поменял формат на yyMMddHHmmss , и ошибка исчезла.
Перевод статьи «How to fix bugs, step by step»