Иногда бывает так, что программа внезапно выдаёт ошибку на ровном месте, хотя до этого она запускалась много раз и без ошибок. Тесты тоже ничего не находят, но ошибка всё равно иногда возникает. Потом снова всё работает правильно, а затем — снова та же ошибка. Такие ошибки называются плавающими, и они раздражают всех: и тестировщиков, и разработчиков, и пользователей.
Рассказываем, что это за ошибки, откуда они берутся и что с ними делать.
Что такое плавающая ошибка
Плавающая ошибка — это такая ошибка, которая:
- не выявляется стандартными тестами;
- проявляется время от времени и всегда непредсказуемым образом;
- не повторяется, если второй раз сделать всё то же самое.
В англоязычной среде такие ошибки называют «гейзенбагами» (heisenbug). Эта игра слов происходит от принципа неопределённости Гейзенберга (или Хайзенберга) из квантовой механики, когда ошибка как бы есть, но её как бы нет.
Откуда берутся плавающие ошибки
Самая частая причина плавающей ошибки — неправильная работа оборудования. Например, на управляющей плате может случайным образом отходить контакт микроконтроллера, при этом внешне всё будет выглядеть как обычно. Этот ненадёжный контакт может пропускать обработку нужного сигнала или, наоборот, отдавать случайные сигналы в контроллер, что и приводит к плавающей ошибке.
Из-за влажности воздуха какие-то контакты в штекерах могут то пропускать, то не пропускать сигналы.
Могут влиять временные файлы программы — как на диске, так и в оперативной памяти. Иногда бывает так, что при создании временных файлов могут использоваться области, с которыми уже работают другие переменные или функции.
Также плавающие ошибки могут возникать из-за неправильного порядка работы с переменными — например, когда мы создаём пустую переменную, компьютер выделяет для неё какой-то участок памяти. Если эта переменная потом долго не используется, оптимизаторы кода могут убрать её объявление из программы, чтобы потом добавить в момент вызова. Но иногда такая оптимизация проходит не совсем правильно, и компьютер даёт переменной случайный адрес в памяти, с которым может работать другая программа. Это приводит к тому, что в этой переменной вдруг могут появиться те значения, которых там быть не должно.
А ещё их может вызывать переполнение стека, когда переполняется какой-то фрагмент памяти. Иногда программа не считает это ошибкой и продолжает работать дальше, но в памяти лежат уже другие данные — а это уже может вызвать проблемы.
Как найти такую ошибку
Для обнаружения плавающих ошибок нужны особые методы тестирования и отладки, например:
- использовать дополнительные инструменты мониторинга,
- создавать сложные сценарии тестирования,
- искусственно создавать нестабильную среду,
- собирать логи каждого шага работы программы.
При любом методе поиска тестировщики получают огромный набор данных, в котором сложно ориентироваться и ещё сложнее — найти ошибку. Поэтому поиск плавающих ошибок оставляют на самый конец, когда все остальные ошибки уже найдены и исправлены.
В некоторых компаниях считается, что нахождение плавающей ошибки — это пропуск в высшую лигу для тестировщиков. Если тестировщик смог найти то, что никто, кроме него, не смог, — он действительно крут и ему можно поручить практически любую задачу в тестировании.
Как описать плавающую ошибку
Чем лучше описана ошибка, тем проще тестировщикам её найти. Это значит, что как только плавающая ошибка проявилась, нужно собрать как можно больше данных о ней, например:
- как выглядит ошибка;
- что в программе делали до этого;
- в какой момент она проявилась;
- как долго программа работала до этого;
- когда она была запущена;
- с какими данными работала;
- на каком железе и с какой операционной системой;
- что делали на этом компьютере последнее время и так далее.
Чем больше данных — тем проще тестировщикам понять, что происходит, и исправить это.
Могут выяснить, что ошибка возникает после какого-то раза запуска программы; в какие-то дни недели; в какие-то числа месяца; когда программой пользуется определённый человек или на определённом компьютере. Вариантов бесконечно много.
Ошибка при работе с плавающей точкой — это оно?
Нет.
Плавающая точка — это способ представления чисел в компьютере с плавающей запятой. В программировании такое часто используется для работы с дробными числами. Вместо того чтобы использовать обычную десятичную запись, числа с плавающей точкой используют два числа — порядок и мантиссу, и всё это в двоичном виде. В зависимости от размера числа положение дробной запятой постоянно меняется, отсюда и название.
Ошибки при работе с плавающей точкой обычно связаны с неправильным округлением чисел, а не с тем, что эта ошибка проявляется время от времени.