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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    Вы начали цикл for с единицы вместо нуля или наоборот. Или, например, подумали, что метод .count() или .length() вернул индекс последнего элемента. Проверьте документацию к языку, чтобы убедиться, что нумерация массивов начинается с нуля или с единицы. Эта ошибка иногда проявляется в виде исключения Index out of range .
    Ваш процесс или поток пытается использовать результат выполнения дочернего до того, как тот завершил свою работу. Ищите использование sleep() в коде. Возможно, на мощной машине дочерний поток выполняется за миллисекунду, а на менее производительной системе происходят задержки. Используйте правильные способы синхронизации многопоточного кода: мьютексы, семафоры, события и т. д.

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

Отладка

Отладка, или debugging, — это поиск (локализация), анализ и устранение ошибок в программном обеспечении, которые были найдены во время тестирования.

Виды ошибок

Ошибки компиляции

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

В интерпретируемых языках (например Python) текст программы команда за командой переводится в машинный код и сразу исполняется. К моменту обнаружения ошибки часть программы уже может исполниться.

Ошибки компоновки

Ошибки связаны с разрешением внешних ссылок. Выявляет компоновщик (редактор связей) при объединении модулей программы. Простой пример — ситуация, когда требуется обращение к подпрограмме другого модуля, но при компоновке она не найдена. Ошибки также просто найти и устранить.

Ошибки выполнения (RUNTIME Error)

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

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

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

Ошибки определения данных или неверное определение исходных данных. Они могут появиться во время выполнения операций ввода-вывода.

К ним относятся:

  • ошибки преобразования;
  • ошибки данных;
  • ошибки перезаписи.

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

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

В эту группу входят:

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

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

Веб-разработчик с нуля

Освойте веб-разработку за 12 месяце и делайте сайты и приложения любой сложности.

Методы отладки программного обеспечения

Метод ручного тестирования

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

Метод индукции

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

Вот как выглядит процесс:

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

Метод дедукции

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

Метод обратного прослеживания

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

Как выполняется отладка в современных IDE

Ранние отладчики, например gdb, представляли собой отдельные программы с интерфейсами командной строки. Более поздние, например первые версии Turbo Debugger, были автономными, но имели собственный графический интерфейс для облегчения работы. Сейчас большинство IDE имеют встроенный отладчик. Он использует такой же интерфейс, как и редактор кода, поэтому можно выполнять отладку в той же среде, которая используется для написания кода.

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

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

Шаг с заходом (step into)

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

Шаг с обходом (step over)

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

Шаг с выходом (step out)

В отличие от step into и step over, step out выполняет не следующую строку кода, а весь оставшийся код функции, исполняемой в настоящее время. После возврата из функции он возвращает управление разработчику. Эта команда полезна, когда специалист случайно вошел в функцию, которую не нужно отлаживать.

Как правило, при пошаговом выполнении можно идти только вперед. Поэтому легко перешагнуть место, которое нужно проверить. Если это произошло, необходимо перезапустить отладку.

У некоторых отладчиков (таких как GDB 7.0, Visual Studio Enterprise Edition 15.5 и более поздних версий) есть возможность вернуться на шаг назад. Это полезно, если пропущена цель либо нужно повторно проверить выполненную инструкцию.

Веб-разработчик с нуля

За 12 месяцев вы освоите базовую верстку, frontend и backend. В конце обучения у вас будет готовое портфолио из проектов.

Виды ошибок в программах

Я учусь на своих ошибках. Ругаю себя за это, но продолжаю ошибаться. С другой стороны — это всё-таки лучше, чем не учиться совсем, и наступать на одни и те же грабли бесконечно.

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

Итак, основных вида всего три:

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

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

Синтаксические ошибки — это ошибки синтаксиса (а то бы вы не догадались))). То есть ошибки правил языка. Например, для Паскаля это будет синтаксической ошибкой:

Потому что после первой строки нет точки с запятой.

Подобные ошибки очень часто совершают новички. И это вгоняет их в ступор — они пугаются и не могут понять, что же не так с их кодом. Хотя если бы они внимательно его посмотрели и прочитали сообщение об ошибке, то легко могли бы исправить её:

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

Потому что в сообщении чётко сказано:

что можно перевести как

То есть компилятор говорит нам: я ожидал увидеть точку с запятой, а нашёл идентификатор READLN .

Логические ошибки в программах

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

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

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

Пример логической ошибки:

Здесь мы сравниваем значение i с числом 15, и выводим сообщение, если i = 15 . Но фишка в том, что в данном цикле i не будет равно 15 НИКОГДА, потому что в цикле переменной i присваиваются значения от 1 до 10.

Эта ошибка довольно безобидная. Здесь мы имеем просто бессмысленный код, который не причинит никакого вреда. Однако представьте, что программа должна выдавать какой-то сигнал тревоги, если i = 15 . Тогда получится, что никакого сигнала пользователь никогда не услышит, даже если случилось что-то страшное. А всё потому, что программист немного ошибся. Вот так вот и падают ракеты и самолёты…

Распространённые логические ошибки в С++ вы можете посмотреть здесь.

Ошибки времени выполнения программы

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

Одна из самых рапространённых ошибок времени выполнения — это неожиданное деление на ноль. Пример:

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

Но представьте, что пользователь введёт ноль. Что тогда будет? Правильно — попытка деления на ноль. А на ноль делить нельзя. Поэтому во время выполнения этой программы произойдёт ошибка, которая очень расстроит пользователя. Потому что в случае, например, с консольным приложением программа просто закроется, и пользователь не поймёт, что это было. Но зато поймёт, что программа — говно, и программы от этого разработчика лучше больше никогда не использовать.

В данном случае, если вы не уверены на 100%, что y будет отличаться от нуля, надо всегда делать проверку на ноль. И хороший код должен быть хотя бы таким:

Ну что же. На этом с видами ошибок пока всё. Изучайте программирование и поменьше ошибайтесь.

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

 

Поиск и исправление ошибок в программе

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

  1. Синтаксические — ошибки, которые допускаются в результате невнимательности программистов: неправильно выбран оператор, пропущена буква или символ, лишние буква, символ, оператор и т. п.

  2. Логические — ошибки, которые возникают от неправильного выполнения скрипта или части кода. Такие ошибки могут привести к критическим ситуациям, когда становится невозможной дальнейшая работа или модернизация программы. Как правило, эта категория ошибок очень трудно обнаруживается.

Синтаксические ошибки

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

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

Вопрос: «Как найти ошибки кода HTML?» решается за пять минут. В сети очень много валидаторов кода HTML — найдите себе подходящий и используйте. К примеру, самым известным из них является «Валидатор от W3C». Данный ресурс предоставит список ошибок HTML с инструкциями и описанием. Вам останется только их исправитьи все будет хорошо.

Таким же образом проверяются синтаксические ошибки CSS и JavaScript:

  • находите нужный валидатор, 

  • находите при помощи него синтаксические ошибки,

  • исправляете ошибки.

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

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

Советы:

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

  2. «Ок, Google!». Если вы нашли ошибку, то есть шанс, что она не уникальна и кто-то с ней уже сталкивался. А это значит, что вполне вероятно, что у кого-то уже есть решение этой проблемы. Поэтому попробуйте найти ее решение в сети.

  3. Ищите строку! Если поиск в сети не дал результатов, то запустите программу в отладчике и попробуйте найти строку кода, где возникает ошибка. Это, скорее всего, не решит проблему, но даст вам хоть какое-то представление о ней и позволит продолжить дальнейшие поиски.

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

  5. Исключайте. Может так случиться, что сразу найти нужную строку кода не получится. В таком случае нужно выявить «проблемный» блок кода. Для этого нужно постепенно отключать компоненты программы, пока не будет выявлен «проблемный» компонент.

  6. Нужно исключить проблему в аппаратном обеспечении. Редкий случай, но бывает так, что проблема с «железом» вызывает ошибки с исследуемой программой. Можно обновить операционную систему, среду разработки, заменить оперативную память и т. д.

  7. Ищите совпадения. Когда возникают ошибки в программе? В одно и то же время? В одном и том же месте? Что общего у пользователей, у которых возникают ошибки? Задавайте подобные вопросы и ищите взаимосвязь. Это может натолкнуть вас на поиск самой проблемы.

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

Заключение

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

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

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

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

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

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

Начало
сеанса отладки

Первый шаг отладки
приложения – это выбор команды Start
Debugging
(F5) на стандартной
панели инструментов или в меню Debug,
после чего приложение запускается в
режиме отладки.

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

Установка
точек останова

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

Установить точку
останова на какой-либо строке кода можно
при помощи щелчка по полю индикаторов
данной строки (рис. 16). Либо можно
установить курсор на нужной строке и
нажать клавишу F9.

Потому что в сообщении чётко сказано:

что можно перевести как

То есть компилятор говорит нам: я ожидал увидеть точку с запятой, а нашёл идентификатор READLN .

Логические ошибки в программах

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

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

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

Пример логической ошибки:

Здесь мы сравниваем значение i с числом 15, и выводим сообщение, если i = 15 . Но фишка в том, что в данном цикле i не будет равно 15 НИКОГДА, потому что в цикле переменной i присваиваются значения от 1 до 10.

Эта ошибка довольно безобидная. Здесь мы имеем просто бессмысленный код, который не причинит никакого вреда. Однако представьте, что программа должна выдавать какой-то сигнал тревоги, если i = 15 . Тогда получится, что никакого сигнала пользователь никогда не услышит, даже если случилось что-то страшное. А всё потому, что программист немного ошибся. Вот так вот и падают ракеты и самолёты…

Распространённые логические ошибки в С++ вы можете посмотреть здесь.

Ошибки времени выполнения программы

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

Одна из самых рапространённых ошибок времени выполнения — это неожиданное деление на ноль. Пример:

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

Но представьте, что пользователь введёт ноль. Что тогда будет? Правильно — попытка деления на ноль. А на ноль делить нельзя. Поэтому во время выполнения этой программы произойдёт ошибка, которая очень расстроит пользователя. Потому что в случае, например, с консольным приложением программа просто закроется, и пользователь не поймёт, что это было. Но зато поймёт, что программа — говно, и программы от этого разработчика лучше больше никогда не использовать.

В данном случае, если вы не уверены на 100%, что y будет отличаться от нуля, надо всегда делать проверку на ноль. И хороший код должен быть хотя бы таким:

Ну что же. На этом с видами ошибок пока всё. Изучайте программирование и поменьше ошибайтесь.

Источник

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

 

Поиск и исправление ошибок в программе

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

  1. Синтаксические — ошибки, которые допускаются в результате невнимательности программистов: неправильно выбран оператор, пропущена буква или символ, лишние буква, символ, оператор и т. п.

  2. Логические — ошибки, которые возникают от неправильного выполнения скрипта или части кода. Такие ошибки могут привести к критическим ситуациям, когда становится невозможной дальнейшая работа или модернизация программы. Как правило, эта категория ошибок очень трудно обнаруживается.

Синтаксические ошибки

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

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

Вопрос: «Как найти ошибки кода HTML?» решается за пять минут. В сети очень много валидаторов кода HTML — найдите себе подходящий и используйте. К примеру, самым известным из них является «Валидатор от W3C». Данный ресурс предоставит список ошибок HTML с инструкциями и описанием. Вам останется только их исправитьи все будет хорошо.

Таким же образом проверяются синтаксические ошибки CSS и JavaScript:

  • находите нужный валидатор, 

  • находите при помощи него синтаксические ошибки,

  • исправляете ошибки.

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

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

Советы:

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

  2. «Ок, Google!». Если вы нашли ошибку, то есть шанс, что она не уникальна и кто-то с ней уже сталкивался. А это значит, что вполне вероятно, что у кого-то уже есть решение этой проблемы. Поэтому попробуйте найти ее решение в сети.

  3. Ищите строку! Если поиск в сети не дал результатов, то запустите программу в отладчике и попробуйте найти строку кода, где возникает ошибка. Это, скорее всего, не решит проблему, но даст вам хоть какое-то представление о ней и позволит продолжить дальнейшие поиски.

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

  5. Исключайте. Может так случиться, что сразу найти нужную строку кода не получится. В таком случае нужно выявить «проблемный» блок кода. Для этого нужно постепенно отключать компоненты программы, пока не будет выявлен «проблемный» компонент.

  6. Нужно исключить проблему в аппаратном обеспечении. Редкий случай, но бывает так, что проблема с «железом» вызывает ошибки с исследуемой программой. Можно обновить операционную систему, среду разработки, заменить оперативную память и т. д.

  7. Ищите совпадения. Когда возникают ошибки в программе? В одно и то же время? В одном и том же месте? Что общего у пользователей, у которых возникают ошибки? Задавайте подобные вопросы и ищите взаимосвязь. Это может натолкнуть вас на поиск самой проблемы.

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

Заключение

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

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

Источник

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

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

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

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

Начало
сеанса отладки

Первый шаг отладки
приложения – это выбор команды Start
Debugging
(F5) на стандартной
панели инструментов или в меню Debug,
после чего приложение запускается в
режиме отладки.

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

Установка
точек останова

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

Установить точку
останова на какой-либо строке кода можно
при помощи щелчка по полю индикаторов
данной строки (рис. 16). Либо можно
установить курсор на нужной строке и
нажать клавишу F9.

Рисунок
16.
Установка
точки останова

Просмотр
данных в отладчике

Когда выполнение
программы в сеансе отладки приостановлено
(например,
при помощи точки
останова), можно
изучить состояние и содержимое ее
переменных и объектов.
Для этого в VS
можно использовать
три вида окон:
Local
(Локальные)
,
Autos
(Видимые)
и Watch
(Контрольные).

Доступ к окнам можно
получить нажав
Debug->Windows->выбрать
нужное окно(Рис. 17)

Рисунок 17. Доступ к
окнам

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

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

чтобы увидеть
значения, связанные с той строкой кода,
на которую вы смотрите, можно использовать
окно Autos.
Это окно показывает значения всех
переменных и выражений, имеющихся в
текущей выполняющейся строке кода или
в предыдущей строке кода. На рис. 19

показано окно Autos
для той же
самой строки кода, которая показана на
рис. 18. Обратите внимание на разницу.

Окна Watch
в VS позволяют
настраивать собственный список переменных
и выражений, за которыми нужно наблюдать
(рис. 20). Окна Watch
выглядят и
ведут себя точно так же, как и окна Local
и Autos.
Кроме того, те элементы, которые вы
размещаете в окнах Watch,
сохраняются между сеансами отладки.

Рисунок
18.
Окно
Local

Рисунок
19.
Окно
Autos

Вы получаете доступ
к окнам Watch
из меню или панели инструментов Debug
(рис. 17).
Четыре окна Watch
(которые называются Watch
1
, Watch
2
, Watch
3
и Watch
4
) позволяют
настроить четыре списка элементов, за
которыми необходимо наблюдать. Эта
возможность может быть особенно полезна
в том случае, когда каждый список
относится к отдельной области видимости
вашего приложения.

Переменную или
выражение в окно Watch
1
можно добавить
из редактора кода. Для этого в редакторе
кода выделите переменную (или выражение),
щелкните по ней правой кнопкой мыши и
выберите пункт Add
Watch.
При этом выделенная переменная (или
выражение) будет помещена в окно Watch
1
. Вы можете
также перетащить выделенный элемент в
это окно.

Рисунок
20.
Окно
Watch
1

Пошаговое
прохождение для поиска ошибки

После того как в
нашем примере отладчик,
встретив точку
останова, прервал
выполнение программы,
далее можно
выполнять код по шагам (режим
трассировки
).
Для этого можно
выбрать команду Step
into
на панели
инструментов Debug
или нажать
функциональную клавишу F11(Рис.
21). Это приведет
к последовательному выполнению кода
по одной строке,
что позволит
вам видеть одновременно и ход выполнения
приложения, и
состояние объектов программы по мере
выполнения кода.
Команда Step
into
(F11) позволяет
продвигаться по коду по одной строке.
Вызов этой
команды выполнит текущую строку кода
и поместит курсор на следующую выполняемую
строку. Важное
различие между Step
into
и другими
похожими командами состоит в

том,
как Step
into
обрабатывает
строки кода, в
которых содержатся вызовы функций.
Если вы находитесь
на строке кода,
которая вызывает
другую функцию программы,
то выполнение
команды Step
into
перенесет вас
на первую строку этой функции.

Если сделать так в
нашем примере,
то вы увидите
ошибку: обнуление
элементов массива должно начинаться
не с элемента с индексом i1,
а со следующего
элемента i1+1.

Команда Step
out
(F10) позволяет
вам сохранять фокус в текущей функции
(не заходя в вызываемые ею подпрограммы),
т. е. вызов Run
out
приведет к
выполнению строки за строкой, но не
заведет вас в вызовы функций и при этом
следующей выполняемой

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

Рис 21. Команда Step
Into

Одной из более
удобных (и
часто упускаемых)
функциональных
возможностей набора инструментов
отладки является функция Run
to
cursor
( Выполнить до текущей позиции)
.
Она работает в
полном соответствии со своим названием.
Вы устанавливаете
курсор на некий код и вызываете эту
команду. Приложение
компилируется и выполняется до тех пор,
пока не доходит
до той строки,
где находится
курсор. В
этой точке отладчик прерывает приложение
и выдает вам эту строку кода для пошагового
прохождения.
Рис. 22.

Рисунок 22. Вызов
команды Run
To
Cursor

Продолжить отладку
после точки останова можно повторным
нажатием на кнопку F5 (Start
Debugging).

Рисунок 23. Результат
работы программы после исправления
ошибки

Рассмотрим пошаговое
выполнение программы с использованием
окна Watch
на простейшем примере.

Пример.

#include
«stdafx.h»

#include
«conio.h»

int
_tmain(int argc, _TCHAR* argv[])

{

int
a,S,i,b;

a=0;

b=0;

i=0;

S=1;

do

{

a=a+1;

b=b+2;

S=(S*a)+(S/b);

i++;

}while(i<5);

printf(«%d»,S);

getch();

return
0;

}

Запускаем
трассировку(Step
Into
)
нажатием
F11 либо
Debug>Step
Into
.
Открываем
окно Watch(Debug>Windows>Watch>Watch1).
Переход на
следующий шаг осуществляется нажатием
кнопки F11.

Рисунок 24. Окно
редактора кода в начале трассировки.

Рисунок 25. Значение
переменных перед первым прохождением
цикла

Рисунок 26. Окно
редактора кода перед первым прохождением
цикла

Рисунок
27. Значения переменных после выполнения
операции а=а+1

Рисунок
28. Значения переменных после выполнения
операции b=b+2

Рисунок
29. Значения переменных после выполнения
операции S=(S*a)+(S/b)

Рисунок
30. Значения переменных после выполнения
операции i++

Рисунок
31. Значения переменных после прохождения
цикла

Рисунок 32. Вывод
итогового значения на экран

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
Источник

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

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

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

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

Начало
сеанса отладки

Первый шаг отладки
приложения – это выбор команды Start
Debugging
(F5) на стандартной
панели инструментов или в меню Debug,
после чего приложение запускается в
режиме отладки.

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

Установка
точек останова

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

Установить точку
останова на какой-либо строке кода можно
при помощи щелчка по полю индикаторов
данной строки (рис. 16). Либо можно
установить курсор на нужной строке и
нажать клавишу F9.

Рисунок
16.
Установка
точки останова

Просмотр
данных в отладчике

Когда выполнение
программы в сеансе отладки приостановлено
(например,
при помощи точки
останова), можно
изучить состояние и содержимое ее
переменных и объектов.
Для этого в VS
можно использовать
три вида окон:
Local
(Локальные)
,
Autos
(Видимые)
и Watch
(Контрольные).

Доступ к окнам можно
получить нажав
Debug->Windows->выбрать
нужное окно(Рис. 17)

Рисунок 17. Доступ к
окнам

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

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

чтобы увидеть
значения, связанные с той строкой кода,
на которую вы смотрите, можно использовать
окно Autos.
Это окно показывает значения всех
переменных и выражений, имеющихся в
текущей выполняющейся строке кода или
в предыдущей строке кода. На рис. 19

показано окно Autos
для той же
самой строки кода, которая показана на
рис. 18. Обратите внимание на разницу.

Окна Watch
в VS позволяют
настраивать собственный список переменных
и выражений, за которыми нужно наблюдать
(рис. 20). Окна Watch
выглядят и
ведут себя точно так же, как и окна Local
и Autos.
Кроме того, те элементы, которые вы
размещаете в окнах Watch,
сохраняются между сеансами отладки.

Рисунок
18.
Окно
Local

Рисунок
19.
Окно
Autos

Вы получаете доступ
к окнам Watch
из меню или панели инструментов Debug
(рис. 17).
Четыре окна Watch
(которые называются Watch
1
, Watch
2
, Watch
3
и Watch
4
) позволяют
настроить четыре списка элементов, за
которыми необходимо наблюдать. Эта
возможность может быть особенно полезна
в том случае, когда каждый список
относится к отдельной области видимости
вашего приложения.

Переменную или
выражение в окно Watch
1
можно добавить
из редактора кода. Для этого в редакторе
кода выделите переменную (или выражение),
щелкните по ней правой кнопкой мыши и
выберите пункт Add
Watch.
При этом выделенная переменная (или
выражение) будет помещена в окно Watch
1
. Вы можете
также перетащить выделенный элемент в
это окно.

Рисунок
20.
Окно
Watch
1

Пошаговое
прохождение для поиска ошибки

После того как в
нашем примере отладчик,
встретив точку
останова, прервал
выполнение программы,
далее можно
выполнять код по шагам (режим
трассировки
).
Для этого можно
выбрать команду Step
into
на панели
инструментов Debug
или нажать
функциональную клавишу F11(Рис.
21). Это приведет
к последовательному выполнению кода
по одной строке,
что позволит
вам видеть одновременно и ход выполнения
приложения, и
состояние объектов программы по мере
выполнения кода.
Команда Step
into
(F11) позволяет
продвигаться по коду по одной строке.
Вызов этой
команды выполнит текущую строку кода
и поместит курсор на следующую выполняемую
строку. Важное
различие между Step
into
и другими
похожими командами состоит в

том,
как Step
into
обрабатывает
строки кода, в
которых содержатся вызовы функций.
Если вы находитесь
на строке кода,
которая вызывает
другую функцию программы,
то выполнение
команды Step
into
перенесет вас
на первую строку этой функции.

Если сделать так в
нашем примере,
то вы увидите
ошибку: обнуление
элементов массива должно начинаться
не с элемента с индексом i1,
а со следующего
элемента i1+1.

Команда Step
out
(F10) позволяет
вам сохранять фокус в текущей функции
(не заходя в вызываемые ею подпрограммы),
т. е. вызов Run
out
приведет к
выполнению строки за строкой, но не
заведет вас в вызовы функций и при этом
следующей выполняемой

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

Рис 21. Команда Step
Into

Одной из более
удобных (и
часто упускаемых)
функциональных
возможностей набора инструментов
отладки является функция Run
to
cursor
( Выполнить до текущей позиции)
.
Она работает в
полном соответствии со своим названием.
Вы устанавливаете
курсор на некий код и вызываете эту
команду. Приложение
компилируется и выполняется до тех пор,
пока не доходит
до той строки,
где находится
курсор. В
этой точке отладчик прерывает приложение
и выдает вам эту строку кода для пошагового
прохождения.
Рис. 22.

Рисунок 22. Вызов
команды Run
To
Cursor

Продолжить отладку
после точки останова можно повторным
нажатием на кнопку F5 (Start
Debugging).

Рисунок 23. Результат
работы программы после исправления
ошибки

Рассмотрим пошаговое
выполнение программы с использованием
окна Watch
на простейшем примере.

Пример.

#include
«stdafx.h»

#include
«conio.h»

int
_tmain(int argc, _TCHAR* argv[])

{

int
a,S,i,b;

a=0;

b=0;

i=0;

S=1;

do

{

a=a+1;

b=b+2;

S=(S*a)+(S/b);

i++;

}while(i<5);

printf(«%d»,S);

getch();

return
0;

}

Запускаем
трассировку(Step
Into
)
нажатием
F11 либо
Debug>Step
Into
.
Открываем
окно Watch(Debug>Windows>Watch>Watch1).
Переход на
следующий шаг осуществляется нажатием
кнопки F11.

Рисунок 24. Окно
редактора кода в начале трассировки.

Рисунок 25. Значение
переменных перед первым прохождением
цикла

Рисунок 26. Окно
редактора кода перед первым прохождением
цикла

Рисунок
27. Значения переменных после выполнения
операции а=а+1

Рисунок
28. Значения переменных после выполнения
операции b=b+2

Рисунок
29. Значения переменных после выполнения
операции S=(S*a)+(S/b)

Рисунок
30. Значения переменных после выполнения
операции i++

Рисунок
31. Значения переменных после прохождения
цикла

Рисунок 32. Вывод
итогового значения на экран

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Логическая ошибка (программирование)

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

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

В С++ логической ошибкой также называется особое исключение (logic_exception).

Связанные понятия

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

Упоминания в литературе

Связанные понятия (продолжение)

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

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

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

Источник

Поиск и исправление логических ошибок в программе или коде HTML

при помощи чего выявляются логические ошибки в программе

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

Поиск и исправление ошибок в программе

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

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

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

Синтаксические ошибки

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

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

Вопрос: «Как найти ошибки кода HTML?» решается за пять минут. В сети очень много валидаторов кода HTML — найдите себе подходящий и используйте. К примеру, самым известным из них является «Валидатор от W3C». Данный ресурс предостави т список ошибок HTML с инструкциями и описанием. Вам останется только их исправить — и все будет хорошо.

Таким же образом проверяются синтаксические ошибки CSS и JavaScript:

н аходите нужный валидатор,

находите при помощи него синтаксические ошибки,

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

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

«Ок, Google!». Если вы нашли ошибку, то есть шанс, что она не уникальна и кто-то с ней уже сталкивался. А это значит, что вполне вероятно, что у кого-то уже есть решение этой проблемы. Поэтому попробуйте найти ее решение в сети.

Исключайте. Может так случиться, что сразу найти нужную строку кода не получится. В таком случае нужно выявить «проблемный» блок кода. Для этого нужно постепенно отключать компоненты программы, пока не будет выявлен «проблемный» компонент.

Ищите совпадения. Когда возникают ошибки в программе? В одно и то же время? В одном и том же месте? Что обще го у пользователей, у которых возника ю т ошибки? Задавайте подобные вопросы и ищите взаимосвязь. Это м ожет натолкнуть вас на поиск самой проблемы.

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

Заключение

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

Мы будем очень благодарны

если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.

Источник

Аннотация: Лекция посвящена описанию вопросов, касающихся отладки приложений и работы с ошибками.

8.1. Ошибки при создании программы

Можно выделить два типа ошибок, с которыми сталкивается программист. Во-первых — это ошибки, которые сопровождают создание программ, а во вторых — ошибки времени выполнения.

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

Приведем несколько примеров синтаксических ошибок.

  • Неправильное ключевое слово. Такая ошибка сразу будет отмечена редактором. Например, если в конструкции цикла For-Next сделать ошибку в ключевом слове For — вы увидите сообщение об ошибке как только попытаетесь перейти к написанию следующей, после начала цикла, строки.
  • Ошибка при объявлении переменной. Если вы забудете указать ключевое слово Dim при объявлении переменной — редактор выдаст сообщение об ошибке. Однако, сделает он это лишь при попытке запуска программы.

А вот — логические ошибки.

  • Неправильное использование операторов. Например, вместо знака обычного деления вы случайно использовали знак целочисленного деления.
  • Расчет какого-либо показателя по неправильной формуле. Например, если неточно расставить скобки в каком-либо выражении — это приведет к ошибке, хотя внешне все может выглядеть правильным.
  • Неправильное использование функций — как встроенных, так и пользовательских. Например, используя функцию Str для получения строкового представления числа, вы не учли, что для положительных чисел эта функция добавляет в начало строки пробел. Далее вы попытались узнать первую цифру числа, вырезав первый символ полученной строки. Естественно, никакой цифры в этом случае не получится — лишь знак пробела для положительных или «минус» для отрицательных чисел.
  • Неправильное использование переменных. Например, вы используете два вложенных цикла для обработки двумерного массива. Одна из цикловых переменных имеет имя i, вторая — j. Они довольно сильно похожи внешне, их можно случайно перепутать при указании индексов массива. К тому же, обрабатывая массив в цикле довольно легко перепутать место каждой из переменных при указании индекса массива. Использование понятных имен переменных (например — my_Age или num_Vozrast для хранения возраста и т.д.) позволяет эффективно бороться с такими ошибками.
  • Случайное использование «новых» переменных. Например, вы предложили пользователю ввести некое значение и записали его в переменную num_Inp, а использовав эту переменную в выражении, напечатали не num_Inp, а num_Ihp. Внешне они похожи, но, присмотревшись, вы можете обнаружить, что имена разные. Еще сложней искать ошибки в латинских именах переменных, в которые «вкрались» русские буквы. Разницу между my_Name и my_Namе вы не увидите, но это — разные переменные — в конце второй вместо латинской e использована русская е. Эффективно бороться с такими ошибками можно, если задать в редакторе опцию обязательного объявления переменных ( Option Explicit ). При появлении необъявленной переменной редактор даст знать об этом.
  • Неправильное использование оператора сравнения. Например, это может быть оператор, который сравнивает некие величины не так, как вы предполагали — вместо знака < вы случайно использовали > или, редактируя сравнение (скажем, скопировав похожий оператор сравнения из другого места программы для ускорения работы), поменяли местами сравниваемые переменные или выражения, не поменяв знака и т.д.

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

8.2. Ошибки при выполнении программы

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

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

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

8.3. Тестирование программ и поиск ошибок

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

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

Если обычные проверки закончились успешно — можно считать, что ваша программа корректно работает, не имеет синтаксических и логических ошибок.

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

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

  • Если программа запрашивает число — введите какое-нибудь слово, очень большое число, ноль, отрицательное число, оставьте поле ввода пустым, введите дробное число. Если вы не предусмотрели никаких специальных мер по обработке ошибок, при выполнении подобных операций вы почти гарантированно встретитесь с проблемами.
  • Попытайтесь запустить программу, открыв несколько окон с документами.
  • Попытайтесь прервать работу программы, а потом снова возобновить ее. Если в вашей программе есть участки, в течение выполнения которых нельзя допускать прерывания работы программы пользователем — вам следует подумать о том, чтобы запретить прерывание работы программы на этих участках.
  • Попытайтесь использовать вашу программу в более старой версии Microsoft Office, в нерусифицированной версии. Обратите внимание, например, на различия расширений имен файлов в Office 2007 и более старых версиях, на различия в объектных моделях. В общем случае программы из более старых версий Office будут работать в Office 2007, однако если они используют какие-то специфические особенности Office — такие программы нуждаются в проверке и обновлении. В то же время, макросы для Office 2007, использующие новые объектные модели, могут не работать или работать неправильно в старых версиях.
  • Попытайтесь поработать с вашей программой на чужом ПК. Вполне возможно, что при таком эксперименте вы столкнетесь с ошибкой. Например, вы программно работаете с файлами на вашем рабочем ПК — если эти файлы отсутствуют на ПК другого пользователя или находятся в других директориях, или тех директорий, которые нужны вашей программе, нет на ПК другого пользователя — вы столкнетесь с ошибкой.
  • Во время работы программы сделайте что-нибудь необычное. Как правило, от пользователей можно ожидать любых странных на первый взгляд действий. Если вы тестируете программу для MS Word, которая правит текст или занимается автоматическим созданием текста, попробуйте во время ее работы переключаться между документами, читать документ, вносить в него правки, выделять произвольные участки текста. То же самое касается MS Excel — во время работы программы попробуйте переключаться между открытыми книгами, между листами, выделять ячейки, попробуйте запустить программу, делая различные листы активными, открыв несколько книг. Результаты такого тестирования могут быть совершенно непредсказуемыми. Проанализировав их, вы можете прити к выводу, что, например, на время выполнения программы нужно скрывать или блокировать документ, пользоваться альтернативными методами работы с документом. Яркий пример — объект Selection в MS Word, который чувствителен к смене выделения в процессе работы, и объект Range, который может работать совсем без создания выделения в тексте.
  • Если ваша программа использует файлы, находящиеся в локальной сети, отключите сеть во время работы программы. Проверьте ее реакцию. То же самое можно сделать, если ваша программа работает с принтером — проверьте ее реакцию на выключенный принтер, на принтер, в котором нет бумаги.
  • Наконец, представьте, что вы — пользователь программы и просто поработайте с ней. А еще лучше — попросите потенциального пользователя немного «пообщаться» с вашей программой. Этот способ позволяет протестировать программу в условиях, максимально приближенных к реальным.

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

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

8.4. Отладка программ в редакторе VBA

Основной метод отладки — это пошаговое исполнение программы с использованием точек останова (breakpoint).

Чтобы создать в программе точку останова, достаточно щелкнуть мышью в редакторе на серой панели напротив команды, на которой нужно остановить выполнение программы. Там появится большая красная точка (рис. 8.1.) — здесь программа будет остановлена в процессе выполнения. Строка будет подсвечена красным цветом.

Точка останова в программе

Рис.
8.1.
Точка останова в программе

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

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

Установить точку останова в строку можно, выделив строку и выбрав команду Debug o Toggle Breakpoint (Отладка o Установить точку останова). Для удаления всех точек останова из программы можно воспользоваться командой Debug o Clear All Breakpoints (Отладка o Очистить точки останова).

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

Так же режим отладки можно включить, нажав во время работы программы комбинацию клавиш Ctr + Pause Break и нажав в появившемся окне кнопку Debug. Текущая строка будет выделена желтым цветом, напротив нее будет установлена желтая стрелочка. Однако такой способ обычно не позволяет точно «попасть» в то место программы, где находится предполагаемая ошибка (рис. 8.2.).

Программа, остановленная во время выполнения

Рис.
8.2.
Программа, остановленная во время выполнения

Чтобы запущенная программа останавливалась на каждой строке, можно запустить ее в режиме Step Into командой Debug o Step Into (Отладка o Пошаговое исполнение). Того же эффекта можно достичь, нажав клавишу F8 на клавиатуре.

Когда программа остановлена, вы можете выполнить следующие действия

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

    Значение переменной во всплывающем окне

    Рис.
    8.3.
    Значение переменной во всплывающем окне

  • Продолжить выполнение программы в режиме Step Into — выбрав соответствующую команду меню или нажав клавишу F8.
  • Отредактировать программу.
  • Продолжить исполнение программы в обычном режиме командой Run o Sub/User Form (Запустить o Процедуру/Форму), нажатием клавиши F5 или соответствующей кнопкой на панели инструментов
  • Остановить выполнение программы командой Run o Reset (Запустить o Перезагрузка) или кнопкой на панели инструментов
  • Воспользоваться другими средствами отладки — окнами Immediate, Locals, Watch.

Помимо режима Step Into существуют следующие режимы отладки, доступные в меню Debug.

  • Step Over (Перейти на следующую строку). Эта команда полезна при отладке программы, содержащей вызовы уже отлаженных процедур. В режиме Step Over отладчик не входит в процедуру, выполняя ее без отладки, после чего переходит на следующую строку. Например, вы выполняете программу в режиме Step Into и при очередной остановке видите, что подсвеченная строка содержит вызов процедуры, которую отлаживать не нужно. Вы выбираете команду Step Over, процедура выполняется без остановок на каждой ее строке, после чего следующая остановка происходит на строке вашей программы, которая идет за вызовом процедуры.
  • Step Out (Выполнить процедуру) — эта команда позволяет выполнить текущую процедуру (например, вызванную из кода основной программы при обычной отладке ) без остановки в каждой строке. Следующая остановка будет сделана на строке, которая следует за вызовом процедуры в основном тексте программы.
  • Run To Cursor (Выполнить до курсора) — выполняет программу до позиции, на которой установлен курсор. Аналогично установке одиночной точки останова.

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

8.10. Каковы характерные ошибки программирования?

Ошибки могут быть допущены на всех
этапах решения задачи — от ее постановки до оформления. Разновидности
ошибок и соответствующие примеры приведены в таблице:

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


8.11. Является ли отсутствие синтаксических ошибок свидетельством правильности программы?

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

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

Примеры синтаксических ошибок:

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

8.12. Какие ошибки не обнаруживаются транслятором?

Существует множество ошибок, которые
транслятор выявить не в состоянии, если используемые в программе
операторы сформированы верно.

Примеры таких ошибок.

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

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

Ошибки в циклах:

  •  
    • неправильное указание начала цикла;
    • неправильное указание условий окончания цикла;
    • неправильное указание числа повторений цикла;
    • бесконечный цикл.

Ошибки ввода-вывода; ошибки при работе с данными:

  •  
    • неправильное задание тип данных;
    • организация считывания меньшего или большего объёма даных, чем требуется;
    • неправильное редактирование данных.

Ошибки в использов нии переменных:

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

Ошибки при работе с массивами:

  •  
    • массивы предварительно не обнулены;
    • массивы неправильно описаны;
    • индексы следуют в неправильном порядке.

Ошибки арифметических операций:

  •  
    • неверное указание типа переменной (например, целочисленного вместо вещественного);
    • неверное определение порядка действий;
    • деление на нуль;
    • извлечение квадратного корня из отрицательного числа;
    • потеря значащих разрядов числа.

Эти ошибки обнаруживаются с помощью тестирования.

8.13. В чем заключается сопровождение программы?

Сопровождение программ — это работы, связанные с обслуживанием программ в процессе их эксплуатации.

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

Программа, предназначеная для длительной эксплуатации, должна иметь соответствующую документацию и инструкцию по её использованию.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

int a = 25;

int b = 8;

float c = a/b;

Console.Write(c);

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

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

Источник

Время на прочтение
6 мин

Количество просмотров 1.3K

Привет, Хабр!

Меня зовут Котов Илья, я Data Scientist и участник профессионального сообщества NTA.

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

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

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

Для начала четко обозначу задачу – это улучшение процесса дистанционного взыскания.

Необходимо найти все диалоги, в которых робот совершает логическую ошибку следующего вида:

Бот задает вопрос о том, закроет ли клиент долг => клиент отвечает отрицательно или неопределенно => бот считает, что ответ положительный и фиксирует это.

Что я подразумеваю под диалогом скажу чуть позже.

Рассмотрим примерный шаблон, по которому бот ведет беседу с клиентом.

  1. Приветствие и информирование о том, что разговор будет записан.

  2. Идентификация клиента.

  3. Информирование о задолженности.

  4. Прощание.

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

Фрагмент диалога, в котором клиент не прошел идентификацию.

Фрагмент диалога, в котором клиент не готов к диалогу.

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

Обзорный план моего решения:

  1. Собрать и обработать все ответы клиентов на вопрос о задолженности.

  2. Разбить ответы клиентов на группы. Этот пункт является скорее подзадачей, которая облегчит разметку. Обзорный осмотр 200 кластеров быстрее, чем просмотр всей коллекции диалогов, которых около 1 000 000.

  3. Разметить эти кластеры вручную, там, где клиент без сомнений говорит о том, что он заплатит или уже заплатил = 1, во всех остальных случаях = 0 (включая неопределенности: *не знаю*, *когда придет зарплата*, *наверное завтра* и так далее).

  4. Если у ответа стоит отметка 0 и при этом бот ведет себя также, как и при 1(то есть думает, что клиент ответил утвердительно), то этот случай я буду считать логической ошибкой и направлять аналитику для дальнейшего осмотра.

Сбор и обработка ответов клиентов

Диалог в рамках данной работы – это отсортированная по времени таблица, у которой есть 2 поля и свой собственный id.

speaker – кто произнес цитату (робот или клиент).

sent – цитата.

Всего таких диалогов около 1 000 000.

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

#список вопросов об оплате
robot_questions = [
    'ВНЕСЕТЕ ПЛАТЕЖ?'
    'ОПЛАТА ПОСТУПИТ ЗАВТРА?',
    'ВЫ ГОТОВЫ ПРОИЗВЕСТИ ОПЛАТУ ЗАВТРА?',
    'ВЫ ГОТОВЫ ОПЛАТИТЬ ЕЁ ЗАВТРА?',
    'ВЫ ГОТОВЫ ОПЛАТИТЬ ЭТУ СУММУ?',
    'ВО ИЗБЕЖАНИЕ НЕГАТИВНЫХ ПОСЛЕДСТВИЙ, ВЫ ГОТОВЫ ПРОИЗВЕСТИ ОПЛАТУ ЗАВТРА?'
]
#ответы клиентов
client_answers = []
#номера таблиц в которых отсутствует вопрос или их по какой-то причине более 1,
#пока для простоты не будем рассматривать эти случаи. 
black_indexes = []
#идем по каждому диалогу и отбираем только те, в которых бот 1 раз задает вопрос из списка, 
#далее забираем ответы клиента.
for table_index, table in enumerate(data):
    search_robot_questions = table.loc[((table['sent'].isin(robot_questions)) & 
                                       	              (table['speaker'] == 'robot'))]
    if search_robot_questions.shape[0] == 1:
        try:
            index = search_robot_questions.index[0] + 1
            client_answers.append(table.iloc[index]['sent'])
        except IndexError:
            black_indexes.append(table_index)
    else:
        black_indexes.append(table_index)

Если смотреть на ответы клиентов, то все они примерно одинаковы, отличия есть в небольших деталях.

Разбивка ответов клиентов на группы

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

import pymorphy2
from gensim.utils import tokenize
MORPH_ANALYZER = pymorphy2.MorphAnalyzer()
#простая предобработка текста(токенизация и приведение к нормальной форме)
def simple_preprocessing(sent: str)-> str:
    return ' '.join([MORPH_ANALYZER.normal_forms(word)[0] for word in tokenize(sent.lower())])
simple_preprocessing('МОЖНО ПАРУ ДНЕЙ ДАЙТЕ МНЕ ЕЩЁ ПОЖАЛУЙСТА Я ПРОСТО С РЕБЁНКОМ ВЫЕХАТЬ НЕ МОГУ')
>>> 'можно пара день дать я ещё пожалуйста я просто с ребёнок выехать не мочь'

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

Для векторизации я буду использовать меру TF-IDF. Мера TF-IDF эффективна для выделения ключевых слов в тексте, это мне и нужно. Цитаты клиентов достаточно короткие, поэтому можно найти слово или несколько слов, которые могут полностью характеризовать всю цитату.

У TF-IDF есть свои преимущества, если сравнивать ее с другими способами векторизации текста:

  1. Легкая интерпретация.

  2. Простота.

  3. Регулирование параметров.

Подробнее о TF-IDF можно прочитать тут.

#предобработка текста
preproc_data = [simple_preprocessing(item) for item in client_answers]
#векторизация
vectorizer = CountVectorizer()
vectorizer_corpus = vectorizer.fit_transform(preproc_data)
tfidf = tfidf_t()
vectors = tfidf.fit_transform(vectorizer_corpus)

Теперь можно использовать алгоритм кластеризации. Я буду использовать DBSCAN. Главное преимущество DBSCAN – это устойчивость к шуму и возможность работы с данными, которые имеют нетипичную форму, однако алгоритм имеет квадратичную сложность, что может привести к долгой работе при больших объемах.

Конфигурация модели

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

Пока для простоты возьму значение eps = (0.1, 0.3, 0.5, 0.7, 1). Чем меньше eps – тем больше объекты в кластере похожи друг на друга.

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

В коде, который представлен ниже, я создаю таблицу с метками кластеров, которые соответствуют определенному параметру eps (0.1, 0.3, 0.5, 0.7, 1).

import seaborn as sns
from sklearn.manifold import TSNE
from sklearn.cluster import DBSCAN 
low_vectors_tsne = TSNE(n_components=2).fit_transform(vectors.toarray())
result = pd.DataFrame()
result['txt'] = client_answers
result['e1'] = low_vectors_tsne[:, 0]
result['e2'] = low_vectors_tsne[:, 1]
for eps in [0.1, 0.3, 0.5, 0.7, 1]:
    result[f'dbscan_{eps}'] = DBSCAN(eps=eps, min_samples=2).fit(low_vectors_tsne).labels_

Результат работы кода:

Посмотрю на результаты и сделаю выборку значений, у которых поле ‘dbscan_1’ = 0 (то есть это все цитаты нулевого класса, при eps = 1).

Теперь посмотрю, например, 5 класс.

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

Визуализирую данные (eps=1). 

Разметка кластеров и отбор кандидатов на ошибку

Получилось более 200 кластеров, которые уже не так трудно разметить вручную, в отличии от 1 000 000 диалогов. Это и была главная цель структурирования. Размечу полученные классы метками 0 или 1.

После разметки остается лишь задать правило, по которому я буду выявлять ошибки робота. Если стоит метка 0 и при этом робот произносит фразы, характерные метке 1, то этот диалог является кандидатом на ошибку.

Отберу те строки, у которых в колонке с диалогами робот говорит:

‘ Я ФИКСИРУЮ ВАШЕ ОБЕЩАНИЕ ОБ ОПЛАТЕ’ хотя бы 1 раз.

То есть данная строка содержится в данном диалоге один или более раз.

candidate = []
for dialog in negative_answer['TABLE'].to_list():
    if dialog[dialog['sent'] == 'Я ФИКСИРУЮ ВАШЕ ОБЕЩАНИЕ ОБ ОПЛАТЕ'].shape[0] > 0:
        candidate.append(dialog)

На выборку из 1 000 000 диалогов получилось 419 диалогов – кандидатов на ошибку. Полученных кандидатов я передаю аналитику для более глубокого анализа.

Подведу итоги

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

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

У этого метода есть и свои недостатки, в векторах отсутствуют семантические знания, то есть модель не видит семантических зависимостей между словами и не сможет ничего сказать о слове, которого нет в датасете. Однако главное его преимущество – это легкое восприятие, относительно не сложная математика и универсальность.

С полным кодом можно ознакомиться по ссылке.

Источник

Понравилась статья? Поделить с друзьями:
  • Как найти логическую ошибку в предложении
  • Как найти логическую ошибку в коде
  • Как найти логические ошибки в программе
  • Как найти логические и стилистические ошибки
  • Как найти лог ошибки при зависании windows 10