Привет! Может случиться так, что ваша система работает у заказчика и периодически ведет себя некорректно из-за логических ошибок, но аварийно не завершается. Одной из причин такого поведения может служить пресловутый catch по всем типам исключений с дальнейшим проглатыванием. Как быть в таком случае? Сейчас я расскажу.
Ситуация особенно усугубляется, если такое поведение не получается воспроизвести локально и поотлаживаться в Visual Studio. В этом случае последней надеждой является исследование дампа памяти процесса. Но его надо снять правильно. Нас интересует дамп не в любой момент времени, а именно в момент возникновения исключений. Получить его можно с помощью утилиты ProcDump от известного Марка Руссиновича. Нас интересует параметр –e 1, который указывает, что дамп памяти должен быть снять в момент возникновения исключения и –ma, указывающий, что нужно снять дамп со всей памяти процесса.
Ситуация особенно усугубляется, если такое поведение не получается воспроизвести локально и поотлаживаться в Visual Studio. В этом случае последней надеждой является исследование дампа памяти процесса. Но его надо снять правильно. Нас интересует дамп не в любой момент времени, а именно в момент возникновения исключений. Получить его можно с помощью утилиты ProcDump от известного Марка Руссиновича. Нас интересует параметр –e 1, который указывает, что дамп памяти должен быть снять в момент возникновения исключения и –ma, указывающий, что нужно снять дамп со всей памяти процесса.
procdump.exe -ma -e 1 16036 (последнее число - ID процесса)
Затем открываем дамп в WinDbg нажатием комбинации Ctrl + D, и в окне команд загружаем Sos. Sos – это расширение WidDbg, которое позволяет в удобном виде получать низкоуровневую информацию из мира .Net в анализируемом процессе или дампе памяти. Подробней о Sos можно почитать тут.
.loadby sos clr
Команда !threads выведет на экран полный список потоков процесса.
В последнем столбце можно увидеть тип исключения, которое возникло в каждом потоке. В нашем случае это DevideByZeroException в потоке 0 (внутренний идентификатор в отладчике). Переключаемся на него командой ~0s и вызываем команду !ClrStack для просмотра стека потока.
Теперь известно место, где произошло исключение. В нашем случае это метод RaiseAndHandleException, Также можно подробней изучить возникшее исключение с помощью команды !pe.
Тут также виден тип исключения и метод, где оно возникло. Этой информации достаточно, чтобы понять причину проблемы и как ее исправить.
Тестовый пример, с помощью которого можно опробовать все описанное, можно взять тут.
Много полезной информации по отладке .Net и использовании WinDbg и Sos можно найти в следующих источниках:
Комментариев нет:
Отправить комментарий