Централизованная обработка исключений
Централизованная обработка исключений
Беляев Алексей
Когда приложение перестает работать в офисе у
разработчика, найти ошибку и исправить ее не составляет труда. Когда же
приложение отказывает у клиента, то трудно найти общий язык с огорченным
пользователем, и понять что ты сделал не так...
Введение
Что такое ошибка? Отвечая на этот вопрос кратко, можно
сказать, что ошибка – это отклонение от описанного поведения. Для разработчика
это означает, что необходимо искать и исправлять причину этого отклонения. Для
программиста контроля качества ПО это означает, что необходимо доработать тесты
и включить их в базовый цикл тестирования приложения. Для руководства это
означает увеличение времени и затрат на разработку продукта.
Ошибки бывают разные, одни воспроизводятся легко,
другие трудно. На поиск одних тратится немного времени, на поиск других уходят
дни. Основная проблема поиска ошибки зачастую связана с недостатком информации
по ее воспроизведению или состоянии приложения в момент возникновения ошибки.
Если бы разработчик имел информацию о том, какая строчка программы содержит
ошибку, ему не составило бы труда исправить ее.
Единственный способ избежать ошибок в программах – это
писать код без ошибок. Но человек не может не делать ошибок, поэтому в любой
программе они есть. Единственное, что разработчик может постараться сделать –
это минимизировать количество ошибок, а также облегчить их поиск и исправление.
В этой статье рассматривается способ, помогающий ускорить поиск и исправление
ошибок.
Windows и необработанные исключения
Когда в приложении, работающем под управлением ОС
Windows (от 9х до ХР), возникает необработанное исключение, операционная
система обрабатывает его, создает dump-файл и записывает в него информацию,
анализируя которую можно восстановить состояние приложения и быстро найти
ошибку. К информации, которую сохраняет операционная система, относится:
информация о потоках;
информация о загруженных модулях;
информация об исключении;
информация о системе;
информация о памяти.
Всю собранную информацию операционная система
предлагает послать в Microsoft для последующего анализа. Учитывая полезность
этой информации и выгоду, которую предоставляет владение ей, необходимо на этапе
проектирования приложения заложить возможность для сбора информации о
приложении во время возникновения исключения для последующего ее анализа. Тогда
разработчики будут иметь больше информации для поиска и исправления ошибок.
Каким образом Windows XP определяет, что в приложении
произошло необработанное исключение? Ответить на этот вопрос можно, если
разобраться с механизмом структурированной обработки исключений (SEH). Все
версии Windows, начиная с версии Windows 95 и Windows NT, поддерживают этот механизм
обработки исключений, позволяющий операционной системе и приложению тесно
взаимодействовать в случае возникновения исключительной ситуации. И если в
каком-либо приложении возникает необработанное исключение, операционная система
обрабатывает его и завершает приложение.
Структурированная обработка ошибок
Структурированная обработка исключений (SEH) – это
предоставляемый системой сервис, вокруг которого библиотеки современных языков
программирования реализуют свои собственные функции для работы с исключениями.
C++-программисты наверняка знакомы с SEH в основном по
использованию конструкций __try ... __except. Встретив в теле функции
конструкцию __try … __except, компилятор, поддерживающий SEH, генерирует код
для регистрации обработчика исключения. Затем, после возникновения исключения,
операционная система ищет подходящий обработчик. Если подходящий обработчик не
найден, операционная система создает dump-файл и завершает работу приложения.
Таким образом, перед нами стоит задача – сделать так,
чтобы после возникновения в приложении необработанного исключения вызывался наш
обработчик.
Для решения этой задачи необходимо выяснить, как
операционная система ищет обработчик исключения. В поисках ответа на этот
вопрос я углублялся в документацию по механизму структурированных исключений,
анализировал системный ассемблерный код, смотрел, что генерирует компилятор,
когда встречает конструкцию __try … __except, но подходящего решения не
находилось. Ни в SDK, ни в DDK я не нашел ничего, что могло бы ответить на этот
вопрос. Анализируя код, генерируемый компилятором для конструкции __try …
__except, я увидел, что для каждого нового обработчика исключений в стеке
создается запись, которая помещается в связанный список. Вот пример простой
функции, который поможет понятнее объяснить это:
void foo()
{
__try
{
}
__except(1)
{
}
}
Похожие работы на - Централизованная обработка исключений
|