Перейти к содержимому

Как можно искать логическую ошибку в программе

  • автор:

Логические ошибки: основные беды начинающих программистов

Логические ошибки

Опытные программисты знают, что ошибки в программе делятся на два основных типа. Первая разновидность — это баги, которые вылавливаются при компиляции. К ним относятся преимущественно проблемы с синтаксисом, явная несовместимости типов и т.д. Эту разновидность багов исправляют на этапе разработки, так как компилятор «вылетает по ошибке». Их просто невозможно не заметить.

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

Выявить этот вид багов удается только на этапе тестирования. И хорошо, если ошибку удается исправить локальной «заплаткой». Нередко приходится менять практически весь алгоритм. А это – дополнительные затраты времени, сил, а в коммерческих проектах – финансовые, а иногда и репутационные потери.

Застраховаться полностью от логических ошибок невозможно. Но вполне реально изучить самые распространенные типы таких багов и проверять на них программу на самых ранних этапах.

Алгоритм – основа всех основ

Написание алгоритма – это самый первый этап разработки, когда идеи только обретают форму еще без привязки к языку программирования. Нередко начинающие программисты относятся к созданию алгоритма «спустя рукава» — делают только «общие наброски» или вообще приступают к кодингу сразу без предварительной проработки логики «на бумаге».

Такой подход возможен при решении учебных задач на 10-15 строк кода. Но при работе над серьезным программным продуктом пренебрежение алгоритмом – почти гарантированный путь к логическим ошибкам и катастрофическим результатам.

Как работать с алгоритмом:

  • Начинайте с малого . Запишите алгоритм упрощенно, в виде «черных ящиков» (логических блоков без подробностей их работы). Это поможет оценить работоспособность идеи в целом.
  • Двигайтесь сверху вниз . Сначала – общая идея «в целом», далее – детализация основных функций и так далее. Не бойтесь ставить «заглушки» и прорабатывать мелкие детали в последнюю очередь. Двигаться сверху вниз проще и с точки зрения логики, и психологически.
  • Пишите команды «от имени компьютера». Помните, что вы имеете дело не с человеком, а с компьютером, который буквально выполняет команды и после каждого шага ждет ответа на вопрос «что делать». Например, логический блок «сохранение документа» будет понятен вам, но не компьютеру. Он вполне подойдет на этапе крупных блоков в качестве заглушки. Но далее придется проработать все действия пошагово с учетом выбранного языка программирования.
  • Делите код на отдельные модули (блоки) , которые можно будет запускать отдельно друг от друга. Это сильно облегчит как алгоритмизацию, так и процесс отладки.
  • Читайте алгоритм «как будто компьютер» . Проверяйте себя на каждом этапе. Главное правило – одинаковые данные всегда должны вести к одинаковым результатам.

Итак, алгоритм написан и проверен со всех сторон. Выбран язык программирования. Начинается процесс кодинга. Давайте разбираться, на что обращать особое внимание.

Что делать начинающим программистам

«Не туда положил»: о типах данных

Здесь проблемы возникают в двух случаях:

  1. При статической типизации в таких языках, как С++, Java или С# неверно определен тип переменной. Большинство подобных ошибок выявляет компилятор. Но здесь есть свои «лазейки» для багов. Например, в С# вполне возможно «положить» вещественное значение в целочисленную переменную. И оно просто округлится до целого. Т.е. вместо 1,3 у вас будет храниться значение 1. Само собой, все дальнейшие вычисления будут содержать ошибку.
  2. При динамической типизации (JavaScript, Python, PHP) неявное приведение типов – самое обычное дело. А потому здесь даже компилятор промолчит в случае ошибки. Например, вы планируете получить целочисленное значение, для чего отправляете результаты вычислений в переменную типа int. Но программа видит «знаки после запятой», и переменная без вашего участия меняет тип на float.

Самый известный пример подобной ошибки – деление двух целых чисел с остатком.

Как вы думаете, какое число будет выведено на экран после выполнения последней строки? По идее, это должно быть 3,125. Но, например, в C# вы увидите целую цифру «3». Причем, тип переменной С будет float, как вы и заказывали.

Здесь проблема в другом: компилятор сначала проводит целочисленное деление, так как определяет переменные A и B как относящиеся к типу int. И полученный результат отправляет в переменную C (тип float). Целое значение (32 разряда) прекрасно помещается в 64-разрядный float, отведенный под хранение результата. Компилятор не видит ошибки. А у вас в программе появляются неточные вычисления, которые могут повлечь за собой большие проблемы.

Аналогичным образом компилятор округлит значение до целого и в Python 2. А уже в Python 3 алгоритм преобразования типов сработает иначе: сначала определится тип переменной, куда отправляется значение, а потом будет проводиться деление. После компиляции кода в Python 3 вы получите c=3,125.

Необходимо четко понимать, как работает преобразование типов в выбранном языке программирования. И в случае любых сомнений проверять результаты в отладчике.

Высвобождение ресурсов: до 100% загрузки процессора

Если вы работаете с языком, где реализована автоматическая сборка мусора, внимательно следите за тем, как происходит высвобождение ресурсов. В отдельных случаях эта полезная функция может начать работать во вред: отбирать для себя максимум памяти, загружать дополнительными задачами процессор, замедлять и даже «подвешивать» программу.

Например, в Java этот процесс работает так:

  • Виртуальная машина проводит поиск ненужных объектов;
  • Составляет из них очередь на удаление;
  • По мере продвижения очереди очищает ячейки памяти.

В результате очередь может стать настолько большой, что компьютер перестанет с ней справляться. А до удаления всех ненужных объектов дело может даже не дойти.

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

Намного надежнее своевременно применять функции типа try-with-resources и try-finally. И все ресурсы очищать в том коде, где вы их получили.

И еще: не забывайте закрывать сессии и файлы сразу после того, как они перестают быть нужны. Это должно быть также естественно, как закрыть скобку в коде.

Конфликт интересов

Конфликт потоков: кто первый успеет?

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

Например: первый поток в результате вычислений получает значение 1, отправляет его в переменную. В это время второй поток перехватывает доступ и обнуляет эту переменную. А первый – сохраняет значение. В результате вы планировали запомнить значение 1. А у вас сразу после вычислений сохраняется 0. И далее копятся ошибка за ошибкой.

Чтобы избежать этой проблемы не забывайте при работе с разными потоками ставить блокировки, чтобы они не обращались одновременно к одним и тем же ресурсам. Можно применять и другие методы синхронизации – события, семафоры, критические секции.

Переменные: склонность к глобализации

Эта ошибка популярна у новичков – стремление объявить сразу все переменные и сделать их глобальными. В результате таких действий вы:

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

На глобальном уровне определяют только необходимый минимум – те самые глобальные переменные, с которыми работают практически все модули. Все остальные объявляйте в тех модулях, где они работают. И не забывайте об идентификаторах ограничения доступа: public, private и protected.

Переполнение буфера в С/С++: «танцы на граблях»

В большинстве современных языках программирования высокого уровня вопрос буферизации решен на автоматическом уровне. Например, Java самостоятельно контролирует размер буфера и определяет границы массивов.

Но нередко для экономии ресурсов программисты используют C-библиотеки. В этом случае очень важно следить за буферизацией. Дело в том, что языки C/С++ очень уязвимы к переполнению буфера. Если он окажется меньше, чем нужно для работы, программа попытается использовать память за пределами выделенного участка. Результат – многочисленные, можно сказать, легендарные ошибки, когда в обрабатываемые данные попадает «неведомый мусор».

Хуже того, это очень известная уязвимость. С 1988 года хакеры пользуются этой «дырой», чтобы подменить адрес возврата в стеке на собственный. Так в программу попадает подставная функция, которая передает управление коду мошенников.

Изучите особенности работы с буфером и методы борьбы с его переполнением, чтобы не пополнить число «танцующих на граблях с 30-летней историей».

Отладка и поиск логических багов

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

  • Пользуйтесь возможностями отладчика вашей IDE . Ставьте контрольные точки, отражайте на консоли ход выполнения и значения переменных, переходите в «пошаговый режим» выполнения в наиболее «подозрительных» участках кода. Так вы быстрее сможете локализовать проблему.
  • Помните: компилятор может неправильно указывать строку с ошибкой . Если вам повезло, и компилятор помог вам выявить баг, не спешите радоваться. При «завершении с ошибкой» вы видите номер строки, в которой выполнение программы стало невозможным. Если проблема в простейшей опечатке (синтаксис), то строка с багом вам известна. В случае логических ошибок вероятнее всего, проблема появилась на более ранних этапах работы программы. А в указанной строке была попытка использовать ошибочные данные, что и привело к аварийному завершению.
  • Старый добрый листинг программы тоже может помочь . Если вы запутались и не знаете, что делать, распечатайте код и попробуйте его «выполнить» как будто вы – и есть компьютер. Шаг за шагом двигайте по командам. Переходите от блока к блоку так, как это делает программа. На каждом этапе вычисляйте и фиксируйте значения переменных (калькулятором пользоваться можно). И сверяйте результаты с ожидаемыми. Все в порядке? Двигайтесь дальше. Что-то не так? Ура! Вы локализовали баг. Можно возвращаться за компьютер и разбираться подробнее в этом фрагменте кода в отладчике.

И самое главное: не бойтесь что-то менять, в том числе, на глобальном уровне. Лучше переписать «сырой» код на раннем этапе разработки практически полностью, чем из-за серьезной логической ошибки терять в скорости и качестве работы программы, пытаясь использовать кучу «заплаток». От ошибок не застрахован никто. Потраченного времени жаль, но это – ваш личный практический опыт. А программа должна работать быстро, надежно и, самое главное, правильно.

Как искать и исправлять ошибки в коде

У начинающих программистов поиск и устранение ошибок (багов — от англ. bug) занимает очень много времени. В этой статье предложена пошаговая инструкция, которая поможет найти и устранить ошибки.

Обложка поста Как искать и исправлять ошибки в коде

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

Шаг 1: Занесите ошибку в трекер

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

  1. Вы забыли какую-то важную деталь об ошибке, например, в чем она заключалась.
  2. Вы могли делегировать ее кому-то более опытному.

Трекер поможет вам не потерять нить размышлений и о текущей проблеме, и о той, которую вы временно отложили. А если вы работаете в команде, это поможет делегировать исправление коллеге и держать все обсуждение в одном месте.

Вы должны записать в трекер следующую информацию:

  1. Что делал пользователь.
  2. Что он ожидал увидеть.
  3. Что случилось на самом деле.

Это должно подсказать, как воспроизвести ошибку. Если вы не сможете воспроизвести ее в любое время, ваши шансы исправить ошибку стремятся к нулю.

Шаг 2: Поищите сообщение об ошибке в сети

Если у вас есть сообщение об ошибке, то вам повезло. Или оно будет достаточно информативным, чтобы вы поняли, где и в чем заключается ошибка, или у вас будет готовый запрос для поиска в сети. Не повезло? Тогда переходите к следующему шагу.

Шаг 3: Найдите строку, в которой проявляется ошибка

Если ошибка вызывает падение программы, попробуйте запустить её в IDE под отладчиком и посмотрите, на какой строчке кода она остановится. Совершенно необязательно, что ошибка будет именно в этой строке (см. следующий шаг), но, по крайней мере, это может дать вам информацию о природе бага.

Шаг 4: Найдите точную строку, в которой появилась ошибка

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

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

Шаг 5: Выясните природу ошибки

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

  1. Ошибка на единицу
    Вы начали цикл for с единицы вместо нуля или наоборот. Или, например, подумали, что метод .count() или .length() вернул индекс последнего элемента. Проверьте документацию к языку, чтобы убедиться, что нумерация массивов начинается с нуля или с единицы. Эта ошибка иногда проявляется в виде исключения Index out of range .
  2. Состояние гонки
    Ваш процесс или поток пытается использовать результат выполнения дочернего до того, как тот завершил свою работу. Ищите использование sleep() в коде. Возможно, на мощной машине дочерний поток выполняется за миллисекунду, а на менее производительной системе происходят задержки. Используйте правильные способы синхронизации многопоточного кода: мьютексы, семафоры, события и т. д.
  3. Неправильные настройки или константы
    Проверьте ваши конфигурационные файлы и константы. Я однажды потратил ужасные 16 часов, пытаясь понять, почему корзина на сайте с покупками виснет на стадии отправки заказа. Причина оказалась в неправильном значении в /etc/hosts , которое не позволяло приложению найти ip-адрес почтового сервера, что вызывало бесконечный цикл в попытке отправить счет заказчику.
  4. Неожиданный null
    Бьюсь об заклад, вы не раз получали ошибку с неинициализированной переменной. Убедитесь, что вы проверяете ссылки на null , особенно при обращении к свойствам по цепочке. Также проверьте случаи, когда возвращаемое из базы данных значение NULL представлено особым типом.
  5. Некорректные входные данные
    Вы проверяете вводимые данные? Вы точно не пытаетесь провести арифметические операции с введенными пользователем строками?
  6. Присваивание вместо сравнения
    Убедитесь, что вы не написали = вместо == , особенно в C-подобных языках.
  7. Ошибка округления
    Это случается, когда вы используете целое вместо Decimal , или float для денежных сумм, или слишком короткое целое (например, пытаетесь записать число большее, чем 2147483647, в 32-битное целое). Кроме того, может случиться так, что ошибка округления проявляется не сразу, а накапливается со временем (т. н. Эффект бабочки).
  8. Переполнение буфера и выход за пределы массива
    Проблема номер один в компьютерной безопасности. Вы выделяете память меньшего объема, чем записываемые туда данные. Или пытаетесь обратиться к элементу за пределами массива.
  9. Программисты не умеют считать
    Вы используете некорректную формулу. Проверьте, что вы не используете целочисленное деление вместо взятия остатка, или знаете, как перевести рациональную дробь в десятичную и т. д.
  10. Конкатенация строки и числа
    Вы ожидаете конкатенации двух строк, но одно из значений — число, и компилятор пытается произвести арифметические вычисления. Попробуйте явно приводить каждое значение к строке.
  11. 33 символа в varchar(32)
    Проверяйте данные, передаваемые в INSERT , на совпадение типов. Некоторые БД выбрасывают исключения (как и должны делать), некоторые просто обрезают строку (как MySQL). Недавно я столкнулся с такой ошибкой: программист забыл убрать кавычки из строки перед вставкой в базу данных, и длина строки превысила допустимую как раз на два символа. На поиск бага ушло много времени, потому что заметить две маленькие кавычки было сложно.
  12. Некорректное состояние
    Вы пытаетесь выполнить запрос при закрытом соединении или пытаетесь вставить запись в таблицу прежде, чем обновили таблицы, от которых она зависит.
  13. Особенности вашей системы, которых нет у пользователя
    Например: в тестовой БД между ID заказа и адресом отношение 1:1, и вы программировали, исходя из этого предположения. Но в работе выясняется, что заказы могут отправляться на один и тот же адрес, и, таким образом, у вас отношение 1:многим.

Если ваша ошибка не похожа на описанные выше, или вы не можете найти строку, в которой она появилась, переходите к следующему шагу.

Шаг 6: Метод исключения

Если вы не можете найти строку с ошибкой, попробуйте или отключать (комментировать) блоки кода до тех пор, пока ошибка не пропадет, или, используя фреймворк для юнит-тестов, изолируйте отдельные методы и вызывайте их с теми же параметрами, что и в реальном коде.

Попробуйте отключать компоненты системы один за другим, пока не найдете минимальную конфигурацию, которая будет работать. Затем подключайте их обратно по одному, пока ошибка не вернется. Таким образом вы вернетесь на шаг 3.

Шаг 7: Логгируйте все подряд и анализируйте журнал

Пройдитесь по каждому модулю или компоненту и добавьте больше сообщений. Начинайте постепенно, по одному модулю. Анализируйте лог до тех пор, пока не проявится неисправность. Если этого не случилось, добавьте еще сообщений.

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

Шаг 8: Исключите влияние железа или платформы

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

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

Ради интереса, переключите кабель питания в другую розетку или к другому ИБП. Безумно? Почему бы не попробовать?

Если у вас возникает одна и та же ошибка вне зависимости от среды, то она в вашем коде.

Шаг 9: Обратите внимание на совпадения

  1. Ошибка появляется всегда в одно и то же время? Проверьте задачи, выполняющиеся по расписанию.
  2. Ошибка всегда проявляется вместе с чем-то еще, насколько абсурдной ни была бы эта связь? Обращайте внимание на каждую деталь. На каждую. Например, проявляется ли ошибка, когда включен кондиционер? Возможно, из-за этого падает напряжение в сети, что вызывает странные эффекты в железе.
  3. Есть ли что-то общее у пользователей программы, даже не связанное с ПО? Например, географическое положение (так был найден легендарный баг с письмом за 500 миль).
  4. Ошибка проявляется, когда другой процесс забирает достаточно большое количество памяти или ресурсов процессора? (Я однажды нашел в этом причину раздражающей проблемы «no trusted connection» с SQL-сервером).

Шаг 10: Обратитесь в техподдержку

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

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

Полезные советы (когда ничего не помогает)

  1. Позовите кого-нибудь еще.
    Попросите коллегу поискать ошибку вместе с вами. Возможно, он заметит что-то, что вы упустили. Это можно сделать на любом этапе.
  2. Внимательно просмотрите код.
    Я часто нахожу ошибку, просто спокойно просматривая код с начала и прокручивая его в голове.
  3. Рассмотрите случаи, когда код работает, и сравните их с неработающими.
    Недавно я обнаружил ошибку, заключавшуюся в том, что когда вводимые данные в XML-формате содержали строку xsi:type=’xs:string’ , все ломалось, но если этой строки не было, все работало корректно. Оказалось, что дополнительный атрибут ломал механизм десериализации.
  4. Идите спать.
    Не бойтесь идти домой до того, как исправите ошибку. Ваши способности обратно пропорциональны вашей усталости. Вы просто потратите время и измотаете себя.
  5. Сделайте творческий перерыв.
    Творческий перерыв — это когда вы отвлекаетесь от задачи и переключаете внимание на другие вещи. Вы, возможно, замечали, что лучшие идеи приходят в голову в душе или по пути домой. Смена контекста иногда помогает. Сходите пообедать, посмотрите фильм, полистайте интернет или займитесь другой проблемой.
  6. Закройте глаза на некоторые симптомы и сообщения и попробуйте сначала.
    Некоторые баги могут влиять друг на друга. Драйвер для dial-up соединения в Windows 95 мог сообщать, что канал занят, при том что вы могли отчетливо слышать звук соединяющегося модема. Если вам приходится держать в голове слишком много симптомов, попробуйте сконцентрироваться только на одном. Исправьте или найдите его причину и переходите к следующему.
  7. Поиграйте в доктора Хауса (только без Викодина).
    Соберите всех коллег, ходите по кабинету с тростью, пишите симптомы на доске и бросайте язвительные комментарии. Раз это работает в сериалах, почему бы не попробовать?

Что вам точно не поможет

  1. Паника
    Не надо сразу палить из пушки по воробьям. Некоторые менеджеры начинают паниковать и сразу откатываться, перезагружать сервера и т. п. в надежде, что что-нибудь из этого исправит проблему. Это никогда не работает. Кроме того, это создает еще больше хаоса и увеличивает время, необходимое для поиска ошибки. Делайте только один шаг за раз. Изучите результат. Обдумайте его, а затем переходите к следующей гипотезе.
  2. «Хелп, плиииз!»
    Когда вы обращаетесь на форум за советом, вы как минимум должны уже выполнить шаг 3. Никто не захочет или не сможет вам помочь, если вы не предоставите подробное описание проблемы, включая информацию об ОС, железе и участок проблемного кода. Создавайте тему только тогда, когда можете все подробно описать, и придумайте информативное название для нее.
  3. Переход на личности
    Если вы думаете, что в ошибке виноват кто-то другой, постарайтесь по крайней мере говорить с ним вежливо. Оскорбления, крики и паника не помогут человеку решить проблему. Даже если у вас в команде не в почете демократия, крики и применение грубой силы не заставят исправления магическим образом появиться.

Ошибка, которую я недавно исправил

Это была загадочная проблема с дублирующимися именами генерируемых файлов. Дальнейшая проверка показала, что у файлов различное содержание. Это было странно, поскольку имена файлов включали дату и время создания в формате yyMMddhhmmss . Шаг 9, совпадения: первый файл был создан в полпятого утра, дубликат генерировался в полпятого вечера того же дня. Совпадение? Нет, поскольку hh в строке формата — это 12-часовой формат времени. Вот оно что! Поменял формат на yyMMddHHmmss , и ошибка исчезла.

Перевод статьи «How to fix bugs, step by step»

Синтаксические и логические ошибки при выполнении программы

Синтаксические и логические ошибки при выполнении программы. Основные средства отладки можно получить через меню 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.

#4 – Что такое баги? Как отследить ошибку?

#4 – Что такое баги? Как отследить ошибку?

Самое плохое что может увидеть программист в своей программе – баг, а еще хуже – баги. В уроке мы поговорим про ошибки, какие они бывают, когда возникают и главное как с ними можно бороться.

Видеоурок

Какие бывают ошибки?

Сразу проясним. В программировани ошибки называют багами. Одна ошибка – один баг.

При написании программ у вас могут возникнуть баги, что разделяются за следующими категориями:

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

Логические ошибки никак не отображаются при построении проекта. Они заключаются в логической промашке выполнения программы. Пример: программа должна вывести число 5, а выводит число 3. Программы выполнилась, но результат не тот что вы ожидали. Такая ошибка может получиться в случае если вы в коде прописали что-то не так. В нашем случае вместо числа 5 написали число 3, поэтому программа сработало, но при этом результат не тот что ожидали. К сожалению, такие ошибки нужно искать в ручном режиме, просматривая строчки написанной вами программы.

Арифметическая ошибка связана с вычислением. Самая частая ошибка такого плана – деление на ноль. Это сделать нельзя и программа выдаст вам ошибку, что квалифицируется как Арифметическая ошибка. Помимо деления на ноль могут быть и другие ошибки связанные с математикой.

Синтаксическая ошибка связана с неверным написанием синтаксисам языка. Каждый язык: C, Java, PHP и другие – имеют специфический синтаксис, в котором будет написан код. Если вы пропустили какой-то необходимый символ при создании какой-либо конструкции в коде, то будет вызвана такая ошибка. Это наиболее простой тип ошибки, так как обычно сама IDE подсказывает что у вас есть такая-то ошибка.

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

Ошибки среды выполнения возникают в момент тестировании программы. Вы ее запустили, работаете в ней и в какой-то момент программа завершается. Думаем вы ни раз такое наблюдали в разных программах. Такое происходит зачастую из-за неверной работы с памятью компьютера. К примеру, можно запустить какую-то задачу на постоянное выполнение. Отведенная память будет перегружена и программа выдаст ошибку. Или же можно в программе попробовать скачать файл с интернета, не убедившись перед этим есть ли доступ к интернету. Если не будет доступа, то программа просто не сможет это сделать и так же выдаст ошибку. Таких примеров сотни и все они будут видны только при тестировании проекта.

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

И наконец, ошибки взаимодействия. Они могут возникнуть в связи с несоответствием программного обеспечения с аппаратным интерфейсом. К примеру, вы делали игру под Андроид, а пробуете запустить под iOS.

Как найти ошибку?

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

Если будет ошибка при построении, то программа не запустится, а в самой IDE будет указан текст ошибки. Такой текст можно загуглить и после найти решение.

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

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

Задание к уроку

Вопросы на проверку

Ответьте на несколько вопросов:

  • расскажите какие ошибки бывают? Назовите хотя бы три вида ошибок.
  • как справиться с ошибкой?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *