Как вы воспроизводите ошибки, которые происходят спорадически?

У нас есть ошибка в нашем приложении, которая не происходит каждый раз, и поэтому мы не знаем его "логику". Я даже не могу воспроизвести его в 100 раз сегодня.

отказ от ответственности: эта ошибка существует и я его видел. Это не pebkac или что-то подобное.

каковы общие подсказки для воспроизведения такого рода ошибок?

28 ответов


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

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

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


добавить какой-то журнал или трассировку. Например, регистрируйте последние действия X, совершенные пользователем перед тем, как вызвать ошибку (только если вы можете установить условие, соответствующее ошибке).


нет общего ответа на вопрос, но вот что я нашел:

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

  2. работайте в обратном направлении и относитесь к нему как к научному расследование. Начните с ошибки, то, что вы видите, неправильно. Разработайте гипотезы о том, что может вызвать его (это творческая/творческая часть, искусство, к которому не у всех есть талант) - и это очень помогает узнать, как работает код. Для каждой из этих гипотез (желательно отсортированных по тому, что вы считаете наиболее вероятным - опять же чистая интуиция здесь) разработайте тест, который попытается устранить ее как причину, и проверьте гипотезу. Любая неудача с предсказанием не означает, что гипотеза неправильный. Проверьте гипотезу, пока она не подтвердится (хотя, поскольку она становится менее вероятной, вы можете сначала перейти к другой гипотезе, просто не сбрасывайте ее со счетов, пока у вас не будет окончательного отказа).

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

  4. дважды проверьте каждое предположение. Так много раз я видел, что проблема не исправляется быстро, потому что какой-то общий вызов метода не был дополнительно исследован, поэтому проблема просто предполагалась неприменимой. - О, это должно быть просто."(См. пункт 1).

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

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


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

на этой частоте 1/100, я бы сказал, что первое, что нужно сделать, это обрабатывать исключения и регистрировать что-нибудь в любом месте, или вы можете потратить еще одну неделю на охоту за этой ошибкой. Также составьте список приоритетов потенциально чувствительных артикуляций и функций в вашем проект. Например : 1 - многопоточность 2 - дикие указатели/ свободные массивы 3 - зависимость от устройств ввода так далее. Это поможет вам сегментировать области, которые вы можете грубая сила до перерыва снова, как это предлагается другими плакатами.


поскольку это язык-агностик, я упомяну несколько аксиом отладки.

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

другой пользователь, тот же компьютер? Тот же пользователь, другой компьютер? Является ли это явление сильно периодическим? Изменяет ли перезагрузка периодичность?

FYI-однажды я видел ошибку, которую испытал один человек. Я буквально имею в виду человека, а не пользователя. Пользователь A никогда не увидит проблему в своей системе, пользователь B сядет на эту рабочую станцию,подписан как пользователь a и может немедленно воспроизвести ошибку. Там не должно быть никакого мыслимого способа для приложения, чтобы знать разницу между физическим телом в кресле. Тем не менее-

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

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


есть хороший шанс, что ваше приложение MTWIDNTBMT (многопоточное, когда оно не должно быть многопоточным), или, возможно, просто многопоточное (чтобы быть вежливым). Хороший способ воспроизвести спорадические ошибки в многопоточных приложениях-разбрызгать такой код вокруг (C#):

Random rnd = new Random();
System.Threading.Thread.Sleep(rnd.Next(2000));

и/или этот:

for (int i = 0; i < 4000000000; i++)
{
    // tight loop
}

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

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


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

изменить: немного больше мыслей: если это приложение gui, запустите тесты с помощью инструмента автоматизации qa, который позволяет воспроизводить макросы. Если это приложение сервисного типа, попробуйте придумать хотя бы догадку о том, что происходит, а затем программно создать шаблоны использования "freak", которые будут использовать код, который вы подозреваете. Создайте более высокие чем обычные нагрузки etc.


какая среда разработки? Для C++ лучшим вариантом может быть запись/воспроизведение VMWare Workstation, см.: http://stackframe.blogspot.com/2007/04/workstation-60-and-death-of.html

другие предложения включают проверку трассировки стека и тщательный обзор кода... серебряной пули действительно нет:)


попробуйте добавить код в приложение, чтобы отслеживать ошибку автоматически, как только это произойдет (или даже предупредить вас по почте / SMS)

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

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


все вышесказанное, плюс бросьте на него некоторую грубую силу soft-robot, которая является полуслучайной, и scater много assert/verify (c/C++, вероятно, похожая на других языках) через код


тонны ведения журнала и тщательный обзор кода-ваши единственные варианты.

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


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


предположим, я начинаю с производственного приложения.

  1. Я обычно добавляю ведение журнала отладки вокруг областей, где, по моему мнению, происходит ошибка. Я настраиваю операторы ведения журнала, чтобы дать мне представление о состоянии приложения. Затем я включил уровень журнала отладки и попросил пользователя/оператора(операторов) уведомить меня о времени следующего возникновения ошибки. Затем я анализирую журнал, чтобы узнать, какие подсказки он дает о состоянии приложения, и если это приводит к лучше понять, что может пойти не так.

  2. Я повторяю Шаг 1, пока не получу хорошее представление о том, где я могу начать отладку кода в отладчике

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

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

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

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

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


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

сказав, что нет серебряной пули. Я чувствую твою боль.


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

вы можете посмотреть оформление по договору


наряду с большим терпением, тихой молитвой и проклятиями вам понадобится:

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

HTH.


предполагая, что вы находитесь в Windows, и ваша "ошибка" - это сбой или какое-то повреждение в неуправляемом коде (C/C++), а затем взгляните на Средство Проверки Приложений из Microsoft. Инструмент имеет ряд остановок, которые можно включить для проверки вещей во время выполнения. Если у вас есть представление о сценарии, в котором возникает ошибка, попробуйте выполнить сценарий (или стресс-версию сценария) с запущенным AppVerifer. Обязательно включите pageheap в AppVerifier или рассмотрите компиляция кода с помощью переключателя / RTCcsu (см.http://msdn.microsoft.com/en-us/library/8wtf2dfz.aspx для получения дополнительной информации).


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

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

и это не гарантирует, что мы все вместе сможем его найти...


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


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

сосредоточьтесь на утилизации ресурсов; многие подлые спорадические ошибки, которые я нашел, были связаны с close\dispose things:).


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

http://code.google.com/p/elmah/

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

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

Они в основном выходят ночью.... в основном


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

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


Это варьируется (как вы говорите), но некоторые из вещей, которые удобны с этим, могут быть

  • немедленно переходит в отладчик, когда возникает проблема, и сбрасывает все потоки (или эквивалент, например, немедленно сбрасывает ядро или что-то еще.)
  • запуск с включенным протоколом, но в остальном полностью в режиме выпуска/производства. (Это возможно в некоторых случайных средах, таких как c и rails, но не во многих других.)
  • делать вещи, чтобы сделать крайние условия на машине хуже... сила низкая память / высокая нагрузка / больше потоков / обслуживание больше запросов
  • убедитесь, что вы на самом деле слушаете то, что пользователи сталкиваются с проблемой на самом деле говорят. Убедиться, что они действительно объясняют соответствующие детали. Это, кажется, тот, который ломает людей в этой области много. Пытаться воспроизвести неправильную проблему скучно.
  • привыкайте к чтению сборки, которая была произведена путем оптимизации компиляторы. Иногда это останавливает людей, и это не применимо ко всем языкам / платформам, но это может помочь
  • будьте готовы признать, что это вина ваша (застройщика). Не попасть в ловушку, настаивая на том, что код идеален.
  • иногда нужно отследить проблему на автомате это происходит.

@С. Марьино - не хватает рэп комментировать =/

tl; dr-сбои сборки из-за времени суток

вы упомянули время дня, и это привлекло мое внимание. Была ошибка, когда-то кто-то оставался позже на работе ночью, пытался построить и совершить, прежде чем они ушли, и продолжал получать неудачу. В конце концов они сдались и пошли домой. Когда они поймали на следующее утро, он построил отлично, они совершили (вероятно, должны были быть более подозрительными =]), и сборка работала для всех. Через неделю или две кто-то задержался и неожиданно потерпел неудачу. Оказывается, в коде была ошибка, которая сделала любую сборку после 7pm break >.>

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

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


нанять тестеров!


Это сработало для действительно странных heisenbugs. (Я бы также рекомендовал получить копию "отладки" Дэйва Арганса, эти идеи частично получены из его идей!)

(0) Проверьте ОЗУ системы, используя что-то вроде Memtest86!

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

он не терпит неудачу 100% времени, поэтому вы должны заставить его терпеть неудачу чаще.

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

посмотреть, если он все еще терпит неудачу. Не чаще ?

храните правильные тестовые записи и меняйте только одну переменную за раз!

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

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

Если в системе нет потоков, нет процессов связи и контактов нет оборудования; это сложно; heisenbugs, как правило, синхронизация, но в случае no-thread no processes более вероятно, что это будут неинициализированные данные или данные, используемые после освобождения, либо на куче или в стеке. Попробуйте использовать проверку, как valgrind.

для проблем с резьбой / несколькими процессами:

попробуйте запустить его на другом количестве процессоров. Если он работает на 1, Попробуйте на 4! Попробуйте принудительно установить 4-компьютерную систему на 1. В основном это гарантирует, что все будет происходить по одному.

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

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

Obversely, попробуйте идти медленнее на timeslices.

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

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


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

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

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

2) записать их в следующий раз, когда вы запустите приложение

3) Когда ваше приложение снова терпит неудачу, у вас есть шаги для воспроизведения сбоя в вашем журнале.

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

http://www.gsd.inesc-id.pt/~nmachado/software/Symbiosis_Tutorial.html

с наилучшими пожеланиями


используйте расширенный Crash reporter. В среде Delphi у нас есть EurekaLog и MadExcept. Другие инструменты существуют в других средах. Или вы можете диагностировать дамп ядра. Вы ищете трассировку стека, которая покажет вам, где он взрывается, как он туда попал, что в памяти и т. д.. Также полезно иметь скриншот приложения,если это пользовательское взаимодействие. И информация о машине, на которой она разбилась (версия ОС и патч, что еще работает в то время и т. д..) Оба инструмента, которые я упомянул, могут это сделать.

Если это что-то, что происходит с несколькими пользователями, но вы не можете воспроизвести его, и они могут, посидите с ними и посмотрите. Если это не очевидно, поменяйтесь местами-вы" за рулем", и они скажут вам, что делать. Таким образом, вы обнаружите тонкие проблемы юзабилити. дважды щелкните кнопку с одним щелчком мыши, например, инициируя повторный вход в событие OnClick. Что-то в этом роде. Если пользователи удаленны, используйте WebEx, Wink и т. д., вести запись они разбивают его, так что вы можете проанализировать воспроизведение.