Плавающая ошибка гейзенбаг

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

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

Что такое плавающий баг?

Нежелательное поведение программы, которое возникает спонтанно и непредсказуемо, называют плавающим багом или гейзенбагом с отсылкой к немецкому физику Вернеру Карлу Гейзенбергу – автору принципа неопределенности из квантовой физики.

Вернер Гейзенберг говорил, что «чем более пристально вы глядите на один предмет, тем меньше внимания вы уделяете чему-то еще».

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

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

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

🐛 Что такое гейзенбаг и как с ним бороться?

Как работать с плавающими багами?

Для избавления от плавающих багов используется традиционный принцип «повторить и разобрать», но с некоторыми оговорками:

  1. Как проверить, что перед вами плавающий баг, а не обычный? Во втором случае вы понимаете, откуда взялась проблема, а в первом – нет. Именно поэтому внимательность и способность ничего не упускать – одно из главных достоинств тестировщика. Самое смешное, неисправленный плавающий и исправленный обычный баги очень похожи – они не воспроизводятся, но плавающий баг может в любой момент вернуться.
  2. Чем выше тестируемость продукта, тем легче найти в нем плавающий баг.
  3. Любая произошедшая по непонятным причинам ошибка может вернуться. «Прошло само» не работает. Код – это четкая структура, поэтому умение локализовать баги важно развивать. Этот навык пригодится, когда ошибка будет воспроизведена, но как – непонятно.
  4. Плавающие баги могут легко воспроизводиться в продуктивной среде и плохо проявляться или вовсе не проявляться в тестовой. Это важно учитывать и соотносить с процессом релиза системы.
  5. В появлении плавающих ошибок может быть виноват целый комплекс причин, поэтому при тестировании используйте таблицы со множеством вариантов. Иногда простой перебор сочетаний различных условий приводит к успеху.
  6. Никогда не пытайтесь скрыть плавающий баг от заказчиков и пользователей. В будущем это может привести к еще большим проблемам.

Яркий пример того, как попытка Intel скрыть ошибку привела к убыткам:

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

Как локализовать ошибку, если первичный анализ ничего не дал?

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

🐛 Что такое гейзенбаг и как с ним бороться?

Почему возникают плавающие баги?

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

Вот примерный список причин, который поможет в случае, если вдохновение вас покинуло:

  1. Переполнение. Какое-либо поле или контейнер могут переполняться и провоцировать сбой при корректной работе связанных с ним функций. В эпоху больших запасов памяти тестировщики часто упускают это из вида. Например, внутри системы могут считаться огромные суммарные значения, и она окажется не способна переварить такое количество символов.
  2. Проблема кода, которую также называют «Проблемой ТЗ». Зачастую плавающий баг связан с тем, как написан код (мы не рассматриваем сейчас некачественную работу, только непредсказуемую). Например, составителю технического задания на разработку очевидно, что при выборке данных нужно взять некий уникальный объект, но разработчик этого знать не может и прописывает свободный выбор. Бывает, что код написан верно, но какое-то сочетание условий приводит не к поломке, а к подмене функций. В этом месте не будет ошибки, но будет неверная работа программы в целом.
  3. Проблемы ввода. Например, в поле свободного ввода пользователь внес непредусмотренные алгоритмом данные, либо ошибочный символ (запятую вместо точки и т.д.). Сюда же относятся ошибки, связанные с использованием клавиатуры вместо мыши или ошибки призрачного ввода, когда данные вносит машина (особенно где-то в середине расчетов). В таких случаях проблему можно обнаружить, проставляя контрольные «стопы» и проверяя работу кода по частям. Еще один вариант – дефектный ввод, когда данные клиент-серверных приложений повреждены или переданы с ошибкой.
  4. Проблемы оборудования возникают, когда ошибки связаны с физическими факторами. Например, из-за перебоев с электропитанием, высоких температур в серверной, физических повреждений компьютера и т.д.
  5. Случайности. Некая комбинация условий может сработать корректно, но впоследствии привести к ошибке.
  6. Deus Ex Machina. Эти проблемы возникают, когда одновременно с вами кто-то еще использует приложение: разработчик, хакер или другой тестировщик.
  7. Неочевидные моменты. При анализе специалисты часто отбрасывают ненужное, чтобы сосредоточиться на важном, а оказывается, что проблема возникает из-за отброшенных ранее вариантов.
  8. Неизвестное. Невозможно учесть все. Например, в системе может быть функция, о которой тестировщику неизвестно, или некие источники искажений. Внутри приложения могут создаваться незадокументированные переменные и т.д. и т.п.

Еще несколько советов по работе с плавающими багами:

  • Всегда проверяйте базу. Характеристики компьютера, что тестируете, исходные данные в документах и по факту.
  • Всегда проверяйте информацию со стороны. Не задавайте вопросы в чате пользователю или коллеге, лучше сходите и посмотрите сами.
  • Если кажется, что все уже проверено от и до, причем несколько раз, попросите коллег посмотреть. Без вас и ваших рассказов, с минимумом вводных.
  • Поищите похожие кейсы и посмотрите, как решались такие вопросы раньше.
  • Сохраняйте все логи. Возможно вам придется сравнивать не только исходный и последний, а еще и промежуточные.
  • Проверяйте то, что на первый взгляд не имеет значения. Даже если вам кажется, что это вообще не относится к вопросу. Часто именно оно оказывается искомым.
  • Проверяйте конфликты на границах разных модулей и систем, особенно если интеграция происходит между продуктами разных разработчиков.
  • Если используете сторонние компоненты, обратитесь в техподдержку разработчика.
  • Если нет никакой информации, ничего не помогает, а ошибка по прежнему не найдена, дайте проблеме отстояться. Вернитесь к ней завтра, а сегодня переключите внимание на другие задачи.
  • Не отчаивайтесь. Ищите инструменты, которые помогут решить вопрос – однажды вы обязательно их найдете.
  • Соотнесите пользу от устранения бага и потраченные на это усилия. Иногда достаточно знать о наличии проблемы: это не баг, это фича.

***

Невыявленные ошибки могут приводить к опасным последствиям. В 1962 году космический аппарат Mariner должен был направиться к Венере, но сломалась антенна и он перешел на автопилот, полетев не туда. В итоге аппарат пришлось взорвать над Атлантическим океаном, а произошло это из-за пропущенного при программировании системы навигации в одной из формул символа. Большинство багов не настолько фатальны, да и системы поиска ошибок стали надежнее, но стремительный рост информационных технологий приводит и к росту сложности систем. Найти в них даже обычные ошибки становится все труднее, а количество плавающих багов увеличивается. Их устранение – уже не начальный уровень в работе тестировщика, но тем интереснее решать подобные задачи. Удачи вам в обучении!

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

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

Что такое плавающая ошибка

Плавающая ошибка — это такая ошибка, которая:

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

В англоязычной среде такие ошибки называют «гейзенбагами» (heisenbug). Эта игра слов происходит от принципа неопределённости Гейзенберга (или Хайзенберга) из квантовой механики, когда ошибка как бы есть, но её как бы нет.

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

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

Из-за влажности воздуха какие-то контакты в штекерах могут то пропускать, то не пропускать сигналы.

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

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

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

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

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

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

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

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

Как описать плавающую ошибку

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

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

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

Могут выяснить, что ошибка возникает после какого-то раза запуска программы; в какие-то дни недели; в какие-то числа месяца; когда программой пользуется определённый человек или на определённом компьютере. Вариантов бесконечно много. 

Ошибка при работе с плавающей точкой — это оно?

Нет. 

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

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

Вёрстка:

Кирилл Климентьев

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

Рассказываем, что нужно знать о гейзенбаге и как его исправить. 

Что такое гейзенбаг
 

Гейзенбаг (плавающий баг) — это возникающие спонтанно нежелательные действия программы. Такие баги ищут QA-специалисты. Алгоритмов, которые автоматически определяют плавающие баги, нет. 

Термин назван в честь физика Вернера Гейзенберга. Он сформулировал принцип неопределенности в квантовой физике.

Причины появления плавающего бага

  • Время

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

  • Память 

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

  • Assert

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

  • Переполнение

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

  • Рандомизация

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

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

Универсального решения нет, но есть техники, которые способны помочь: 

  • Мониторинг системных процессов

Важно, чтобы никакой другой процесс не мешал основному. 

  • Запуск на CPU вместо GPU. Графический процессор дает прирост производительности, но программное обеспечение по умолчанию может его не поддерживать. Выключите графический процессор в своей системе и попробуйте запустить его на CPU.
     
  • Проверка кода на наличие генераторов случайных чисел. Нужно протестировать его, находя генераторы случайных чисел, и отследить случайный вывод для удачных и ошибочных прогонов.
     
  • Запуск на одном узле NUMA гарантирует, что плавающий баг возник не из-за проблем с архитектурой системы. Между узлами NUMA часто наблюдается нестабильность межсоединений.
     
  • Изменение зависимости ПО. Важно, чтобы гейзенбаг не исходил от внешнего программного компонента. Например, вместо использования TensorFlow, оптимизированного для Intel с DNNLv1.1, можно попробовать Vanilla TensorFlow (созданный из исходных кодов или установленный с помощью pip).
     
  • Удаление лишних функций по очереди позволит выяснить, какая из них — источник плавающего бага.
     
  • Запуск стресс-тестов поможет выявить потенциальные ошибки в экстремальных условиях. Но тестирование не доказывает отсутствие ошибок. Стресс-тесты только позволяют снизить риск незамеченных ошибок в рабочей среде.
     
  • Использование специальных алгоритмов для обнаружения потенциального состояния гонки (Race condition). Алгоритм набора блокировок сообщает о потенциальном состоянии гонки, когда к общей памяти обращаются два или более потоков, удерживающих общую блокировку. Он может сообщать о ложных срабатываниях. Алгоритм «происходит до» основан на частичном упорядочении событий (любой инструкции, включая чтение/запись и блокировки) в распределенных системах внутри и между потоками. Этот алгоритм генерирует очень мало ложных срабатываний, но он чувствителен к порядку выполнения, поэтому может потребоваться запустить его несколько раз, прежде чем удастся обнаружить состояние гонки, вызывающее плавающий баг.

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

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

#2. The Intel Inspector помогает находить и отлаживать ошибки потоковой передачи, памяти и постоянной памяти на ранних этапах цикла проектирования.

#3. Kiuwan — инструмент статического анализа кода. Он обнаруживает угрозы безопасности до того, как они попадут в рабочую среду. 

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

  • Использование инструментов дебаггинга:

C ++: UDB. Находит и исправляет ошибки. 

C #: RevDeBug. Исправляет ошибки при диагностике сбоев программного обеспечения. 

Python: RevPDB. Позволяет перемещаться вперед и назад.

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

Что такое плавающий баг?​

Нежелательное поведение программы, которое возникает спонтанно и непредсказуемо, называют плавающим багом или гейзенбагом с отсылкой к немецкому физику Вернеру Карлу Гейзенбергу – автору принципа неопределенности из квантовой физики.

Вернер Гейзенберг говорил, что «чем более пристально вы глядите на один предмет, тем меньше внимания вы уделяете чему-то еще».

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

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

31596e84cf63d2db3cfaa1412bfeca62.jpg

Как работать с плавающими багами?​

Для избавления от плавающих багов используется традиционный принцип «повторить и разобрать», но с некоторыми оговорками:

  1. Как проверить, что перед вами плавающий баг, а не обычный? Во втором случае вы понимаете, откуда взялась проблема, а в первом – нет. Именно поэтому внимательность и способность ничего не упускать – одно из главных достоинств тестировщика. Самое смешное, неисправленный плавающий и исправленный обычный баги очень похожи – они не воспроизводятся, но плавающий баг может в любой момент вернуться.
  2. Чем выше тестируемость продукта, тем легче найти в нем плавающий баг.
  3. Любая произошедшая по непонятным причинам ошибка может вернуться. «Прошло само» не работает. Код – это четкая структура, поэтому умение локализовать баги важно развивать. Этот навык пригодится, когда ошибка будет воспроизведена, но как – непонятно.
  4. Плавающие баги могут легко воспроизводиться в продуктивной среде и плохо проявляться или вовсе не проявляться в тестовой. Это важно учитывать и соотносить с процессом релиза системы.
  5. В появлении плавающих ошибок может быть виноват целый комплекс причин, поэтому при тестировании используйте таблицы со множеством вариантов. Иногда простой перебор сочетаний различных условий приводит к успеху.
  6. Никогда не пытайтесь скрыть плавающий баг от заказчиков и пользователей. В будущем это может привести к еще большим проблемам.

Яркий пример того, как попытка Intel скрыть ошибку привела к убыткам:
В выпускавшихся Intel в 1994 году процессорах Pentium была проблема с некорректным делением чисел с плавающей запятой. В компании посчитали, что дефект может повлиять на работу очень узкого круга пользователей, и решили его скрыть. Возникший в обществе резонанс заставил Intel изменить позицию и принес убытков на $475 млн.

Как локализовать ошибку, если первичный анализ ничего не дал?​

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

5521f17c0dc7950036a8e945f7805594.jpg

Почему возникают плавающие баги?​

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

  1. Переполнение. Какое-либо поле или контейнер могут переполняться и провоцировать сбой при корректной работе связанных с ним функций. В эпоху больших запасов памяти тестировщики часто упускают это из вида. Например, внутри системы могут считаться огромные суммарные значения, и она окажется не способна переварить такое количество символов.
  2. Проблема кода, которую также называют «Проблемой ТЗ». Зачастую плавающий баг связан с тем, как написан код (мы не рассматриваем сейчас некачественную работу, только непредсказуемую). Например, составителю технического задания на разработку очевидно, что при выборке данных нужно взять некий уникальный объект, но разработчик этого знать не может и прописывает свободный выбор. Бывает, что код написан верно, но какое-то сочетание условий приводит не к поломке, а к подмене функций. В этом месте не будет ошибки, но будет неверная работа программы в целом.
  3. Проблемы ввода. Например, в поле свободного ввода пользователь внес непредусмотренные алгоритмом данные, либо ошибочный символ (запятую вместо точки и т.д.). Сюда же относятся ошибки, связанные с использованием клавиатуры вместо мыши или ошибки призрачного ввода, когда данные вносит машина (особенно где-то в середине расчетов). В таких случаях проблему можно обнаружить, проставляя контрольные «стопы» и проверяя работу кода по частям. Еще один вариант – дефектный ввод, когда данные клиент-серверных приложений повреждены или переданы с ошибкой.
  4. Проблемы оборудования возникают, когда ошибки связаны с физическими факторами. Например, из-за перебоев с электропитанием, высоких температур в серверной, физических повреждений компьютера и т.д.
  5. Случайности. Некая комбинация условий может сработать корректно, но впоследствии привести к ошибке.
  6. Deus Ex Machina. Эти проблемы возникают, когда одновременно с вами кто-то еще использует приложение: разработчик, хакер или другой тестировщик.
  7. Неочевидные моменты. При анализе специалисты часто отбрасывают ненужное, чтобы сосредоточиться на важном, а оказывается, что проблема возникает из-за отброшенных ранее вариантов.
  8. Неизвестное. Невозможно учесть все. Например, в системе может быть функция, о которой тестировщику неизвестно, или некие источники искажений. Внутри приложения могут создаваться незадокументированные переменные и т.д. и т.п.

Еще несколько советов по работе с плавающими багами:​

  • Всегда проверяйте базу. Характеристики компьютера, что тестируете, исходные данные в документах и по факту.
  • Всегда проверяйте информацию со стороны. Не задавайте вопросы в чате пользователю или коллеге, лучше сходите и посмотрите сами.
  • Если кажется, что все уже проверено от и до, причем несколько раз, попросите коллег посмотреть. Без вас и ваших рассказов, с минимумом вводных.
  • Поищите похожие кейсы и посмотрите, как решались такие вопросы раньше.
  • Сохраняйте все логи. Возможно вам придется сравнивать не только исходный и последний, а еще и промежуточные.
  • Проверяйте то, что на первый взгляд не имеет значения. Даже если вам кажется, что это вообще не относится к вопросу. Часто именно оно оказывается искомым.
  • Проверяйте конфликты на границах разных модулей и систем, особенно если интеграция происходит между продуктами разных разработчиков.
  • Если используете сторонние компоненты, обратитесь в техподдержку разработчика.
  • Если нет никакой информации, ничего не помогает, а ошибка по прежнему не найдена, дайте проблеме отстояться. Вернитесь к ней завтра, а сегодня переключите внимание на другие задачи.
  • Не отчаивайтесь. Ищите инструменты, которые помогут решить вопрос – однажды вы обязательно их найдете.
  • Соотнесите пользу от устранения бага и потраченные на это усилия. Иногда достаточно знать о наличии проблемы: это не баг, это фича.

***
Невыявленные ошибки могут приводить к опасным последствиям. В 1962 году космический аппарат Mariner должен был направиться к Венере, но сломалась антенна и он перешел на автопилот, полетев не туда. В итоге аппарат пришлось взорвать над Атлантическим океаном, а произошло это из-за пропущенного при программировании системы навигации в одной из формул символа. Большинство багов не настолько фатальны, да и системы поиска ошибок стали надежнее, но стремительный рост информационных технологий приводит и к росту сложности систем. Найти в них даже обычные ошибки становится все труднее, а количество плавающих багов увеличивается. Их устранение – уже не начальный уровень в работе тестировщика, но тем интереснее решать подобные задачи. Удачи вам в обучении!

Источник статьи: https://proglib.io/p/chto-takoe-geyzenbag-i-kak-s-nim-borotsya-2021-02-28

Это — справочный материал о гейзенбагах. Говорим о том, как они выглядят и какое отношение имеют к мейнфреймам — прародителям облака.


/ фото Lars Zimmermann CC BY

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

Название «гейзенбаг» отсылает к принципу неопределенности Гейзенберга из квантовой механики. В общих чертах его можно описать как неожиданное изменение свойств наблюдаемого объекта в результате факта наблюдения.

История

Автором термина «гейзенбаг» считается сотрудник исследовательского центра IBM Брюс Линдсей (Bruce Lindsay). Он внес вклад в развитие реляционных баз данных и занимался разработкой корпоративной СУБД IBM System R.

В 1985 году во время учебы в университете Беркли Брюс и Джим Грей (James Nicholas Gray), американский ученый в области теории вычислительных систем, трудились над ОС CAL-TSS. Она писалась специально для двухпроцессорного мейнфрейма Control Data 6400 [PDF, стр.3], на котором военные обрабатывали большие объемы данных.

Само собой, в процессе разработки возникали баги. Но несколько из них были особенными — как только инженеры пытались их исправить, они исчезали. В то время Линдсей как раз изучал физику и принцип Гейзенберга в частности. Внезапно Линдсея осенило — они с Греем стали свидетелями аналогичного явления: ошибки исчезали, потому что наблюдение влияло на свойства объекта. Отсюда и пошло название «гейзенбаг».

Эту историю Линдсей рассказал в интервью с представителями Ассоциации вычислительной техники (ACM) в 2003 году.

Примеры гейзенбагов

Пользователи в сети и на тематических платформах вроде Stack Overflow поделились несколькими примерами гейзенбагов, с которыми они встречались в своих проектах. Один из резидентов SO пытался вычислить площадь фигуры между двумя кривыми с точностью до трех знаков после запятой. Для отладки алгоритма на C++ он добавил строку:

cout << current << endl;

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

#include <iostream>
#include <cmath>

using namespace std;

double up = 19.0 + (61.0/125.0);
double down = -32.0 - (2.0/3.0);
double rectangle = (up - down) * 8.0;

double f(double x) {
return (pow(x, 4.0)/500.0) - (pow(x, 2.0)/200.0) - 0.012;
}

double g(double x) {
return -(pow(x, 3.0)/30.0) + (x/20.0) + (1.0/6.0);
}

double area_upper(double x, double step) {
return (((up - f(x)) + (up - f(x + step))) * step) / 2.0;
}

double area_lower(double x, double step) {
return (((g(x) - down) + (g(x + step) - down)) * step) / 2.0;
}

double area(double x, double step) {
return area_upper(x, step) + area_lower(x, step);
}

int main() {
double current = 0, last = 0, step = 1.0;

do {
last = current;
step /= 10.0;
current = 0;

for(double x = 2.0; x < 10.0; x += step) current += area(x, step);

current = rectangle - current;
current = round(current * 1000.0) / 1000.0;
//cout << current << endl; //<-- COMMENT BACK IN TO "FIX" BUG
 } while(current != last);

cout << current << endl;
return 0;
}

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

Еще одной историей про гейзенбаг поделились инженеры, работавшие со средой языка Smalltalk-80 на Unix. Они заметили, что система зависала, если оставить её на какое-то время без дела. Но после перемещения курсора мыши, все вновь работало как обычно.

Проблема была связана с планировщиком Unix, который снижал приоритет задач, которые простаивают. В какой-то момент приоритет понижался настолько, что процессы в Smalltalk не успевали завершаться. Стек задач разрастался и «вешал» программу. Когда пользователь двигал курсор, ОС восстанавливала приоритет и все возвращалось на круги своя.

Другие *баги

Есть еще ряд терминов, которые описывают разного рода ошибки: Борбаг, Мандельбаг, Шрёдинбаг.

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

/ фото OLCF at ORNL CC BY

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

Что касается мандельбага, то это ошибка, из-за которой система ведет себя хаотично и непредсказуемо. Феномен назван в честь физика, математика и создателя фрактальной геометрии Бенуа Мандельброта.

Что в итоге

Примеров гейзенбагов (и других *багов) — множество. Их очень сложно искать, но причины возникновения обычно банальны: неинициализированная переменная, ошибки синхронизации в многопоточной среде или проблемы с алгоритмами удаления «мёртвого» кода. Получается, что для борьбы с подобными ошибками их нужно отсекать еще на этапе проектирования приложения.


Из блога о корпоративном IaaS:

  • Avito.ru: как облако IaaS помогает в организации бизнеса компании
  • Что нужно знать о PCI DSS: обзор стандарта
  • Как изменилась жизнь с наступлением DNS Flag Day
  • Как IaaS помогает развивать бизнес: задачи, которые решит облако
  • 9 полезных советов для плавного перехода в облако

Понравилась статья? Поделить с друзьями:
  • Плавающая ошибка абс то горит то перестает
  • Плавают обороты ошибок нет ваз 2114
  • Пкзо код ошибки субд 21
  • Пишет ошибка 502
  • Пишет ошибка 5001