Как вы исправляете ошибку, которую не можете повторить?
Вопрос говорит обо всем. Если у вас есть ошибка, о которой сообщают несколько пользователей, но в журнале нет записи об ошибке, возникшей в ней, и ошибка не может быть повторена, как бы вы ни старались, как вы ее исправите? Или даже ты можешь?
Я уверен, что это случилось со многими из вас там. Что вы делали в этой ситуации, и каков был конечный результат?
Изменить: меня больше интересует то, что было сделано с необъяснимой ошибкой, а не неразрешимой ошибкой. Неразрешимые ошибки таковы, что вы, по крайней мере, знаете, что существует проблема, и в большинстве случаев у нее есть отправная точка для ее поиска. В случае, если вы не можете найти, что вы делаете? Ты вообще можешь что-нибудь сделать?
15 ответов
Они известны как Heisenbugs.
язык
Различные языки программирования будут иметь свой вкус ошибок.
С
Добавление операторов отладки может сделать проблему невозможной для дублирования, потому что сам оператор отладки смещает указатели (достаточно далеко, чтобы избежать SEGFAULT). Проблемы с указателями - это кошмар для отслеживания и репликации, но есть отладчики (такие как GDB и DDD), которые могут помочь.
Джава
Приложение, которое имеет несколько потоков, может показывать свои ошибки только с очень определенной синхронизацией или последовательностью событий. Неправильные реализации параллелизма могут вызвать взаимоблокировки в ситуациях, которые трудно реплицировать.
JavaScript
Некоторые веб-браузеры печально известны утечками памяти. Код JavaScript, который отлично работает в одном браузере, может вызвать некорректное поведение в другом браузере. Использование сторонних библиотек, которые были тщательно протестированы тысячами пользователей, может быть полезным, чтобы избежать некоторых неясных ошибок.
Среда
В зависимости от сложности среды, в которой выполняется приложение (в котором есть ошибка), единственным выходом может быть упрощение среды. Работает ли приложение:
- на сервере?
- на рабочем столе?
- в веб-браузере?
В какой среде приложение создает проблему?
- развитие?
- тестовое задание?
- производство?
Выйдите из посторонних приложений, убейте фоновые задачи, остановите все запланированные события (задания cron), удалите подключаемые модули и удалите надстройки браузера.
сетей
Поскольку сеть имеет важное значение для многих приложений:
- Обеспечение стабильных сетевых подключений, включая беспроводные сигналы.
- Надежно ли восстанавливается программное обеспечение после сбоев сети?
- Все ли соединения закрыты правильно, чтобы освободить файловые дескрипторы?
- Люди используют машину, которой не следует?
- Мошеннические устройства взаимодействуют с сетью машины?
- Есть ли рядом заводы или радиомачты, которые могут создавать помехи?
- Размеры пакетов и частота находятся в пределах номинальных диапазонов?
- Все ли сетевые устройства подходят для интенсивного использования полосы пропускания?
консистенция
Уничтожьте как можно больше неизвестных:
- Изолировать архитектурные компоненты.
- Удалите ненужные или, возможно, проблемные (конфликтующие) элементы.
- Деактивировать различные модули приложения.
Удалите все различия между производством, тестированием и разработкой. Используйте то же оборудование. Выполните точно такие же шаги, чтобы настроить компьютеры. Согласованность является ключевым.
логирование
Используйте либеральные объемы журналирования, чтобы сопоставить произошедшие события. Изучите журналы на наличие явных ошибок, проблем с синхронизацией и т. Д.
аппаратные средства
Если с программным обеспечением все в порядке, рассмотрите аппаратные неисправности:
- Надежны ли физические сетевые соединения?
- Есть ли свободные кабели?
- Правильно ли установлены чипы?
- Все ли кабели имеют чистые соединения?
- Является ли рабочая среда чистой и свободной от пыли?
- Были ли какие-либо скрытые устройства или кабели повреждены грызунами или насекомыми?
- Есть ли плохие блоки на дисках?
- Вентиляторы процессора работают?
- Может ли материнская плата питать все компоненты? (Процессор, сетевая карта, видеокарта, диски и т. Д.)
- Могут ли электромагнитные помехи быть виновником?
И в основном для встраиваемых:
- Недостаточный обход поставок?
- Загрязнение доски?
- Плохие паяные швы / плохое оплавление?
- Процессор не сбрасывается, когда напряжение питания выходит за допустимые пределы?
- Неисправность сбрасывается, потому что питающие шины питаются от портов ввода / вывода и не разряжаются полностью?
- Защелка вверх?
- Плавающие входные контакты?
- Недостаточные (иногда отрицательные) запасы шума на логических уровнях?
- Недостаточные (иногда отрицательные) временные поля?
- Оловянные усы?
- ESD повреждение?
- ОУР расстраивает?
- Ошибка чипа?
- Неправильное использование интерфейса (например, I2C вне платы или при наличии мощных сигналов)?
- Расовые условия?
- Контрафактные компоненты?
Сеть против Локальной
Что происходит, когда вы запускаете приложение локально (т.е. не по сети)? Другие серверы испытывают те же проблемы? База данных удалена? Можете ли вы использовать локальную базу данных?
Прошивка
Между аппаратным и программным обеспечением находится прошивка.
- BIOS компьютера обновлен?
- Батарея BIOS работает?
- Синхронизированы ли часы BIOS и системные часы?
Время и статистика
Сроки проблемы трудно отследить:
- Когда возникает проблема?
- Как часто?
- Какие другие системы работают в это время?
- Является ли приложение чувствительным ко времени (например, будут ли високосные дни или дополнительные секунды вызывать проблемы)?
Соберите точные числовые данные по проблеме. Проблема, которая на первый взгляд может показаться случайной, на самом деле может иметь шаблон.
Управление изменениями
Иногда проблемы появляются после обновления системы.
- Когда впервые возникла проблема?
- Что изменилось в среде (аппаратное и программное обеспечение)?
- Что происходит после отката к предыдущей версии?
- Какие различия существуют между проблемной версией и хорошей версией?
Управление библиотекой
Разные операционные системы имеют разные способы распространения конфликтующих библиотек:
- В Windows есть DLL Ад.
- Unix может иметь множество неработающих символических ссылок.
- Файлы библиотеки Java могут быть одинаково кошмарными для разрешения.
Выполните новую установку операционной системы и включите только вспомогательное программное обеспечение, необходимое для вашего приложения.
Джава
Убедитесь, что каждая библиотека используется только один раз. Иногда контейнеры приложения имеют другую версию библиотеки, чем само приложение. Это может быть невозможно воспроизвести в среде разработки.
Используйте инструмент управления библиотекой, такой как Maven или Ivy.
отладка
Код метода обнаружения, который запускает уведомление (например, журнал, электронная почта, всплывающее окно, звуковой сигнал пейджера), когда происходит ошибка. Используйте автоматическое тестирование для отправки данных в приложение. Используйте случайные данные. Используйте данные, которые охватывают известные и возможные крайние случаи. В конце концов ошибка должна появиться снова.
Спать
Стоит повторить то, что упоминали другие: спать на нем. Проведите время вдали от проблемы, завершите другие задачи (например, документацию). Будьте физически далеки от компьютеров и занимайтесь физическими упражнениями.
Обзор кода
Пройдите код, построчно, и опишите, что каждая строка делает с вами, сотрудником или резиновой уткой. Это может привести к пониманию того, как воспроизвести ошибку.
Космическое излучение
Космические Лучи могут перевернуть биты. Это не такая большая проблема, как в прошлом, из-за современной проверки ошибок памяти. Программное обеспечение для аппаратного обеспечения, которое оставляет защиту Земли, подвержено проблемам, которые просто не могут быть воспроизведены из-за случайности космического излучения.
инструменты
Нечасто, но бывает, особенно для нишевых инструментов (например, компилятор микроконтроллера C, страдающий от переполнения таблицы символов).
Если это приложение с графическим интерфейсом, неоценимо наблюдать, как клиент генерирует ошибку (или пытается). Они, несомненно, будут делать то, о чем вы никогда не догадались (не ошибочно, просто по-другому).
В противном случае, сконцентрируйте свои усилия в этой области. Записывайте почти все (вы можете извлечь это позже) и заставить свое приложение также создавать дамп среды. например, тип машины, тип виртуальной машины, используемая кодировка.
Сообщает ли ваше приложение номер версии, номер сборки и т. Д.? Это необходимо для точного определения версии, которую вы отлаживаете (или нет!).
Если вы можете управлять своим приложением (например, с помощью JMX, если вы находитесь в мире Java), тогда используйте соответствующую область. Хранить статистику, например, запросы + параметры, время выполнения и т. Д. Используйте буферы для хранения последних 'n' запросов / ответов / версий объектов / чего угодно и выгружайте их, когда пользователь сообщает о проблеме.
Если вы не можете воспроизвести это, вы можете это исправить, но не можете знать, что вы это исправили.
Я сделал свое лучшее объяснение о том, как ошибка была вызвана (даже если я не знал, как эта ситуация может возникнуть), исправил это и убедился, что если ошибка обнаружится снова, наши механизмы уведомления позволят будущему разработчику знаю то, что я хотел бы знать. На практике это означало добавление событий журнала, когда пути, которые могли вызвать ошибку, были пересечены, и метрики для связанных ресурсов были записаны. И, конечно же, следя за тем, чтобы тесты в целом хорошо выполняли код.
Решение о том, какие уведомления добавить, является вопросом целесообразности и сортировки. Поэтому в первую очередь решается, сколько времени разработчик потратит на ошибку. На него нельзя ответить, не зная, насколько важна ошибка.
У меня были хорошие результаты (больше не появлялись, код был лучше) и плохие (потратил слишком много времени, не решая проблему, независимо от того, была ли ошибка исправлена или нет). Вот для чего нужны оценки и приоритеты.
Иногда мне просто нужно сидеть и изучать код, пока не найду ошибку. Попробуйте доказать, что ошибка невозможна, и в процессе вы можете выяснить, где вы можете ошибиться. Если вам действительно удается убедить себя, что это невозможно, предположим, что вы где-то напутали.
Это может помочь добавить кучу проверок ошибок и утверждений, чтобы подтвердить или опровергнуть ваши убеждения / предположения. Что-то может потерпеть неудачу, чего вы никогда не ожидаете.
Это может быть сложно, а иногда почти невозможно. Но мой опыт показывает, что вы рано или поздно сможете воспроизвести и исправить ошибку, если потратите на нее достаточно времени (если это потраченное время того стоит, другое дело).
Общие предложения, которые могут помочь в этой ситуации.
- Если возможно, добавьте больше журналов, чтобы у вас было больше данных при следующем появлении ошибки.
- Спросите пользователей, могут ли они повторить ошибку. Если да, вы можете попросить их повторить это, наблюдая за их плечом, и, надеюсь, выяснить, что вызывает ошибку.
Считать. Жесткий. Запереть себя, не допустить вмешательства.
Однажды у меня была ошибка, когда доказательством был шестнадцатеричный дамп поврежденной базы данных. Цепочки указателей систематически облажались. Все программы пользователя и программное обеспечение нашей базы данных работали безупречно при тестировании. Я смотрел на это в течение недели (это был важный клиент), и после устранения десятков возможных идей я понял, что данные были распределены по двум физическим файлам, и произошло повреждение, когда цепочки пересекали границы файлов. Я понял, что в случае сбоя операции резервного копирования / восстановления в критической точке два файла могут оказаться "не синхронизированными" и восстановлены в разные моменты времени. Если вы затем запустите одну из программ клиента на уже испорченных данных, она выдаст именно те цепочки указателей, которые я видел. Затем я продемонстрировал последовательность событий, которые точно воспроизвели коррупцию.
Предполагая, что вы уже добавили все записи, которые, по вашему мнению, могли бы помочь, и это не... две вещи приходят на ум:
Работайте в обратном направлении от сообщенного симптома. Подумайте сами... "что я хотел создать симптом, о котором сообщалось, какой фрагмент кода мне нужно выполнить, и как мне добраться до него и как мне добраться до этого?" D приводит к C приводит к B приводит к A. Примите, что, если ошибка не воспроизводима, то обычные методы не помогут. Мне приходилось много часов смотреть на код с такими мыслительными процессами, чтобы найти ошибки. Обычно это оказывается чем-то действительно глупым.
Помните первый закон отладки Боба: если вы не можете что-то найти, это потому, что вы ищете не в том месте:-)
Обсудите проблему, прочитайте код, часто довольно много. Часто мы делаем это парами, потому что вы обычно можете аналитически исключить возможности довольно быстро.
Есть два типа ошибок, которые вы не можете повторить. То, что вы обнаружили, и то, что обнаружил кто-то еще.
Если вы обнаружили ошибку, вы сможете повторить ее. Если вы не можете воспроизвести его, значит, вы просто не учли все факторы, способствующие возникновению ошибки. Вот почему всякий раз, когда у вас есть ошибка, вы должны документировать ее. Сохраните журнал, получите скриншот и т. Д. Если нет, то как вы можете доказать, что ошибка действительно существует? Может быть, это просто ложное воспоминание?
Если кто-то обнаружил ошибку, и вы не можете ее воспроизвести, обязательно попросите ее повторить. Если они не могут воспроизвести это, вы пытаетесь повторить это. Если вы не можете воспроизвести это быстро, игнорируйте это.
Я знаю, это звучит плохо, но я думаю, что это оправдано. Время, затрачиваемое на копирование ошибки, обнаруженной кем-то другим, очень велико. Если ошибка реальна, это произойдет снова естественно. Кто-то, может быть, даже вы, снова наткнетесь на него. Если это трудно воспроизвести, то это также редко, и, вероятно, не нанесет слишком много урона, если это произойдет еще несколько раз.
Вы можете быть намного более продуктивным, если будете тратить свое время на работу, исправление других ошибок и написание нового кода, чем пытаться воспроизвести загадочную ошибку, которую вы даже не можете гарантировать. Просто подождите, пока он снова появится естественным образом, тогда вы сможете тратить все свое время на его исправление, а не тратить свое время на его обнаружение.
Измените код там, где вы думаете, что проблема возникает, так что дополнительная информация отладки где-то записана. когда это произойдет в следующий раз, у вас будет все необходимое для решения проблемы.
Начните с изучения того, какие инструменты у вас есть. Например, при сбоях на платформе Windows перейдите к WinQual, поэтому, если это ваш случай, теперь у вас есть информация о сбое при сбое. Можете ли вы использовать инструменты статического анализа, которые обнаруживают потенциальные ошибки, инструменты анализа времени выполнения, инструменты профилирования?
Затем посмотрите на вход и выход. Что-то похожее во входных данных в ситуациях, когда пользователи сообщают об ошибке, или что-то неуместное в выводе? Составьте список отчетов и найдите шаблоны.
Наконец, как заявил Дэвид, посмотрите на код.
Попросите пользователя дать вам удаленный доступ к своему компьютеру и все увидите сами. Попросите пользователя сделать небольшое видео о том, как он воспроизводит эту ошибку, и отправьте ее вам.
Конечно, оба не всегда возможны, но если они есть, это может прояснить некоторые вещи. Обычный способ поиска ошибок остается прежним: разделение частей, которые могут вызвать ошибку, попытка понять, что происходит, сужение кодового пространства, которое может вызвать ошибку.
Существуют такие инструменты, как gotomeeting.com, с помощью которых вы можете поделиться экраном с вашим пользователем и наблюдать за его поведением. Там может быть много потенциальных проблем, таких как количество программ, установленных на их компьютерах, некоторые утилиты, конфликтующие с вашей программой. Я считаю, что gotomeeting, это не единственное решение, но могут быть проблемы с тайм-аутом, медленная проблема с интернетом.
В большинстве случаев я бы сказал, что программы не сообщают вам правильные сообщения об ошибках, например, в случае, когда java и C# отслеживают все исключения. Не перехватывайте все, но сохраняйте точку, в которой вы можете перехватывать и регистрировать. Ошибки интерфейса трудно решить, если вы не используете инструменты удаленного рабочего стола. И большую часть времени это может быть ошибка даже в стороннем программном обеспечении.
Если вы работаете с действительно значительным приложением, у вас, вероятно, есть очередь из 1000 ошибок, большинство из которых определенно воспроизводимы.
Поэтому, боюсь, я бы, вероятно, закрыл ошибку как WORKSFORME (Bugzilla), а затем занялся исправлением некоторых более существенных ошибок. Или делать все, что решит руководитель проекта.
Конечно, делать случайные изменения - плохая идея, даже если они локализованы, потому что вы рискуете внести новые ошибки.