![]() |
|
Модераторы: feodorv, GremlinProg, xvr, Fixin |
![]()
|
|
| BearFear |
|
||||||||||||||||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 93 Регистрация: 10.8.2012 Репутация: нет Всего: нет |
Всем приуэт. Возникла следующая дилемма. Для весьма простенькой программы надо предоставить возможность вывода информации об ошибках (замучала меня эта тема блин). После прочтения статей и бла-бла-бла... в общем родился вот такой велосипед с тремя колесами и одной педалью.
В данном случае, создается объект для данного потока, устанавливающий ExceptionHandler для системы и принимающий указатель на функцию shelled_main которая заменяет стандартный мэйн. Далее, вызывается shelled_main и в случае необходимости кидается throw который и обрабатывается указанным try-catch. В случае возникновения исключения stl соответственно обрабатывается условия под исключения stl. В случае если throw без аргумента (класса исключения) то соответственная ветка catch(...). (поправка: пустой throw вызовет unexpected)
Объект shell предназначен для установки обработчиков как для main, так и для потоков, которые создаются отдельным объектом, внутри прокси-функции так же производится подобная установка try-catch и вызов пользовательской функции, которая должна выполняться в контексте потока.
Фактически, такой код приведет к генерации от 1го до 2х исключений подряд. В случае систем исключения, вызывается exception_handler класса shell для данного потока. В случае stl исключения, сначала вызывается исключение уровня try-catch где производится формирование инфы под одну гребенку и вызов системного исключения с уникальным (отличным от системных кодов) кодом исключения. Фактически, цель этого велосипеда, в случае какой либо ошибки, собрать инфу в лог. Повторюсь, ПО позволяет слетать в случае внезапного чиха, так как задача ПО очень тривиальна, хоть и работает с сетью. В общем должны отлавливаться все ошибки и формирование лога проихводится почти одинаково для всех видов ошибок\исключений, будь то рантайм или логические.
Для примера, объект принимает в конструкторе имя модуля и номер строки где возникла логическая ошибка. Это дело можно будет потом допустим поменять на что то иное, например код ошибки, который внутри объекта будет использоваться как индекс описания ошибки из файла, и в таком случае на выходе получим уже описание ошибки как для stl::[some_error].
Собстно код, тут только один комментарий. Данный код пока что не эффективен в силу недоделанности системы. Но отделяет от итогового варианта лишь два момента, которые пока что просто не написал. 1) нет статического глобального объекта строки, в которую будут сваливаться имя модуля и код 2) нет реализации вывода в лог из exception_handler и вызовов RaiseException в конструкциях try-catch
Ну тут все ясно, это прототип shelled_main функции главного потока процесса. В итоге, как бы, программист начинает кодирование отсюда. Все остальное является как бы не то что бы закрытым... как бы шаблоном проекта, каркасом последующих приложений.
Для примера, дропается throw который будет обработан catch(shell_exception&) и будет выведена инфа о факте исключения, с подробностями.
Класс-поток, который по сути ничем не отличается внутри от главного потока (в отношении к велосипеду).
Вот собственно и весь код. Хотелось бы узнать, братцы, является ли такой велосипед целесообразным в данных условиях: 1 - ПО не предназначено для отлова и решения ошибок, так как расчитано на других юзверей. Система должна быть простой настолько, что бы ошибки сводились к отчету об ошибке и отправке на сервер в случае если ошибка не логическая, а stl или системная. О логической ошибке пользователь должен будет прочитать лог и уже сделать вывод, что у него случилось 2 - ПО не обладает важными данными которые надо сохранять или оперировать локально, это графическое ПО которое всего лишь может отсылать ошибки на сервер (для статистики о багах и собственно что бы знать, что исправлять). 3 - Формат лога об ошибках один для всех ситуаций и выводится в xml формат для его более простого просмотра с помощью другой утилиты, а так же что бы сервер смог например прочитать лог и сохранить нужную для разработов инфу на баг тракере, откуда уже будут разбирать задания все кому не лень. Это сообщение отредактировал(а) BearFear - 2.9.2012, 01:13 |
||||||||||||||||||
|
|||||||||||||||||||
| BearFear |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 93 Регистрация: 10.8.2012 Репутация: нет Всего: нет |
Ай, чуть не забыл. Компилятор MinGW.
|
|||
|
||||
| BearFear |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 93 Регистрация: 10.8.2012 Репутация: нет Всего: нет |
У меня есть только одно сомнение (может о других я не знаю), на счет вызова системного экцепшена из другого экцепшена. Не знаю чем это может быть черевато, так как не до конца еще понимаю всю подноготную односвязного списка обработчиков.
|
|||
|
||||
| BearFear |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 93 Регистрация: 10.8.2012 Репутация: нет Всего: нет |
Жалко с Касперски не дружу, он бы точно, фыркнув, щелчком пальца решил такой вопрос, ухоха.
Это сообщение отредактировал(а) BearFear - 1.9.2012, 22:02 |
|||
|
||||
| BearFear |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 93 Регистрация: 10.8.2012 Репутация: нет Всего: нет |
В excpt.h нашел строчки, которые определяют макросы __try1 и __except1, в теле которых выполняется асм инлайн по установке обработчиков ошибок. Завтра займусь проверкой, если это то что я думаю, то всю мою конструкцию можно будет переписать одной функцией и обработчика с указанием ее хэндла в __try1(exception_handler). Это существенно сократит код.
А ваще, в манере захватчика-террориста, лучше даже будет сделать свой макрос с красивым именем
Это сообщение отредактировал(а) BearFear - 1.9.2012, 23:06 |
|||
|
||||
| BearFear |
|
||||||||||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 93 Регистрация: 10.8.2012 Репутация: нет Всего: нет |
Прикольно
Используя __cyg_profile_func_[enter|exit] можно довести до автоматизма некоторые вещи, например автоматическая установка обработчиков для определенных функций. Живые есть? Самому с собой не прикольно болтать Это сообщение отредактировал(а) BearFear - 2.9.2012, 00:01 |
||||||||||||
|
|||||||||||||
| BearFear |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 93 Регистрация: 10.8.2012 Репутация: нет Всего: нет |
Обнаруживается плавающая ошибка:
- код исключения не всегда верный - аргументы не всегда владеют верными указателями происходит все в блоке вызова RaiseException внутри catch. Почему такое может происходить? Это сообщение отредактировал(а) BearFear - 2.9.2012, 19:39 |
|||
|
||||
| BearFear |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 93 Регистрация: 10.8.2012 Репутация: нет Всего: нет |
Ну что, никто не сможет помочь? Никто не знает как в низах работают STL исключения?
Это сообщение отредактировал(а) BearFear - 2.9.2012, 21:20 |
|||
|
||||
| kosmonaFFFt |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 538 Регистрация: 14.4.2008 Где: Иннополис Репутация: нет Всего: 5 |
А зачем использовать массив char и длину, когда есть ::std::string? А что касается исключений, то я например использую ::boost::exception для проброса информации об ошибке в блок catch, отдельно ловлю stl исключения, и даже не парюсь на тему низкоуровневых вещей со всякими ассемблерами, и специфичными только для винды вещами (пишу один и тот же проект попеременно то в linux, то в винде)... -------------------- ![]() |
|||
|
||||
| GremlinProg |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2706 Регистрация: 9.8.2005 Где: Тюмень Репутация: 99 Всего: 106 |
ну и зачем этот, к тому же "вложенный" велосипед? stl и так перехватывает свой собственный SEH (__try-__except), генерируя c++ исключение (try-catch) со своим классом, какой смысл после этого переводить все обратно в SEH? ну поставь просто свой собственный SEH в майн'е и фантазируй дальше как душе угодно опять сомнительный велосипед
как-то условия не очень вяжутся с определением если не хочется трогать ПО, в плане диагностики, как ты эту диагностику проведешь-то? разворачивая стек? а смысл тогда в "номер строки где возникла логическая ошибка" и т.п.? ты же не имеешь эту информацию в произвольном участке кода, где может возникнуть исключение ну и смотри тогда простой дамп исключения, которое и так винда тебе генерирует и предлагает отослать (баг-репорт), там уже это все развернуто и городить огород не нужно или просто поставь Unhandled-фильтр и генерируй свой репорт с версией ПО, адресом и кодом исключения Добавлено через 7 минут и 22 секунды кстати, это скорее C++-исключения, а не STL -------------------- "Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины." |
|||
|
||||
| BearFear |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 93 Регистрация: 10.8.2012 Репутация: нет Всего: нет |
Да, придется отказаться от вложения исключения. Я толком не смог разобраться почему такое происходит, но после С++ отката аргументы для RaiseException перезаписываются, разумеется в обработчик исключений попадает черт пойми что. В принципе, для исправления ситуации надо пару трок поменять. Убрать RaisedException из catch блоков и добавить туда код логирования. Опять таки, это только для main, скажем так, на крайний случай. Далее я определил макрос critical_error который переопределяет вызов throw с указанием модуля и строки + еще добавил комментарий. Выглядит так critical_error("comment"); На выходе уже идет "source.cpp:45 comment".
Массив char использовал что бы при отладке не ковыряться в куче подвызовов string объекта отказываться от try-catch я не собираюсь, опять таки, это только самый низкий уровень который выше системного __try __catch. В коде shelled_main и выше будут простые try-catch с возможностью отката неправильных объектов (без перегруженных операторов new) и прочих прелестей. Просто выгоднее и удобнее как для обработки так и для генерации, использовать один алгоритм логирования, в котором будет указано время, адрес, код. аргументы исключения. Стек вызовов в той же Olly отображается, генерить его локально в лог смысла нет. Достаточно знать адрес исключения (начало инструкции до исключения) что бы поставить брейкпоинт там и соблюдая все условия слета, смоделировать ситуацию. Вот. Спасибо ребят, очень важно было мнение со стороны, хоть какое нибудь |
|||
|
||||
| BearFear |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 93 Регистрация: 10.8.2012 Репутация: нет Всего: нет |
Да, в общем так и сделал. Сначала долго проверял, может быть созданный в try секции shell_exception объект затирается до того как его используют коды в catch по ссылке... но все не то. В общем, теперь добавился объект report, который работает с файлом лога (что бы не писать повторяющийся код вывода в лог). Собстно он весьма гуманно реагирует на запросы о выводе строк, достаточно всего лишь вызвать соответствующий из трех методов для вывода:
А) контекста Б) текстового описания ошибки для stl или пользовательского throw В) событие (дружелюбное описание события с выводом циферок и прочего в блок комментариев в логе. Позволяет более ясно видеть картину в соотношении со стеком вызовов). Всем спасибо, жалко что не удалось разобраться с обобщением логирования, но и то хорошо. Как нибудь все таки это дело расковыряю, как с асмом подружусь окончательно. Всему свое время. Это сообщение отредактировал(а) BearFear - 3.9.2012, 21:29 |
|||
|
||||
![]()
|
| Правила форума "C/C++: Системное программирование и WinAPI" | |
|
|
На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы . Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |