Есть блок кода, в котором возникает исключение (довольно большой). Блок защищен оператором try, исключение перехватывается в catch(...) (других catch нет). Неизвестно что вызывает исключение и в каком конкретно месте оно возникает. Как получить более подробную информацию и локализовать проблемное место?
Здравствуйте, Linuxoid, Вы писали:
L>Есть блок кода, в котором возникает исключение (довольно большой). Блок защищен оператором try, исключение перехватывается в catch(...) (других catch нет). Неизвестно что вызывает исключение и в каком конкретно месте оно возникает. Как получить более подробную информацию и локализовать проблемное место?
ну во первых попробовать catch(std::exception& e), а во вторых скажите в какой системе разработки вы работаете
Здравствуйте, Linuxoid, Вы писали:
L>Есть блок кода, в котором возникает исключение (довольно большой). Блок защищен оператором try, исключение перехватывается в catch(...) (других catch нет). Неизвестно что вызывает исключение и в каком конкретно месте оно возникает. Как получить более подробную информацию и локализовать проблемное место?
Если это .NET студия,
то запусти приложение в дебагере.
Затем открой диалог "Debug/Exception..."
и поставь "Break into the debugger" для C++ Exceptions.
Впрочем для других исключений можешь это тоже выставить.
Linuxoid wrote:
> Есть блок кода, в котором возникает исключение (довольно большой). Блок защищен оператором try, исключение перехватывается в catch(...) (других catch нет). Неизвестно что вызывает исключение и в каком конкретно месте оно возникает. Как получить более подробную информацию и локализовать проблемное место?
Если сорс код доступен, то переносимый способ — это задефайнить throw:
В момент выдачи исключения на стандартный поток вывода будет выдано имя файла и номер строки. И позволяет обрабатывать исключения, где используются не классы, а например int-овые константы.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, MaximE, Вы писали:
ME>Если сорс код доступен, то переносимый способ — это задефайнить throw:
<skipped>
Может я чего-то не допонял, но каким образом мне это поможет? Я же не кидаю исключение руками, оно генерится программой неизвестно где и почему (известен только блок кода).
Здравствуйте, Linuxoid, Вы писали:
L>Есть блок кода, в котором возникает исключение (довольно большой). Блок защищен оператором try, исключение перехватывается в catch(...) (других catch нет). Неизвестно что вызывает исключение и в каком конкретно месте оно возникает. Как получить более подробную информацию и локализовать проблемное место?
Из ваших постов не понятно, располагаете ли вы таки исходными текстами вашего сервиса. Если раполагаете, то хороший способ подсказал MaximE
: переопределив throw через define вы можете получить в catch информацию о месте, откуда исключение было порождено. А далее наводняете это место отладочными печатями и т.д. и т.п.
Еще один способ, если исходники доступны: отключать по очереди участки большого кода (коментируя их или через #if 0/#endif). Если у вас есть test case в котором исключение постоянно появляется, то повторяя этот test case на разных фрагментах вы найдете ситуацию, когда исключение не возникает. Далее таким же образом можно обработать найденый фрагмент и т.д.
Еще один способ, если исходники доступны: вставлять отладочную печать перед каждым throw. А затем смотреть, где чего выскочило. Если отладочные печати не удовлетворяют по соображениям скорости (был упомянут real-time), то можно поступить так: завести буфер, в который записывать какие-то метки (строки или целочисленные константы). Перед каждым throw вставить добавление в этот буфер уникальной метки (например, переопеделив throw через define). А в catch посмотреть, что за метка оказалась в буфере.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Linuxoid wrote:
> Здравствуйте, MaximE, Вы писали: > > ME>Если сорс код доступен, то переносимый способ — это задефайнить throw: > > <skipped> > > Может я чего-то не допонял, но каким образом мне это поможет? Я же не кидаю исключение руками, оно генерится программой неизвестно где и почему (известен только блок кода).
k. wrote:
> Здравствуйте, MaximE, Вы писали: > > VC7 выдает следующее: > > d:\repository\SyncServer\Client-Side\qqq\qqq.cpp(20) : error C2512: 'std::runtime_error' : no appropriate default constructor available > > в то же время, если поправить вот так, то работает: > >
L>Может я чего-то не допонял, но каким образом мне это поможет? Я же не кидаю исключение руками, оно генерится программой неизвестно где >и почему (известен только блок кода).
определить тип исключения программно в рантайме можно только если есть предположения о его типе
тогда ставим несколько catch-ей для каждого предполагаемого базового класса исключения
Здравствуйте, MaximE, Вы писали:
ME>Linuxoid wrote:
>> Здравствуйте, MaximE, Вы писали: >> >> ME>Если сорс код доступен, то переносимый способ — это задефайнить throw: >> >> <skipped> >> >> Может я чего-то не допонял, но каким образом мне это поможет? Я же не кидаю исключение руками, оно генерится программой неизвестно где и почему (известен только блок кода).
ME>Исходники тебе доступны?
Да, доступны. Кстати, это только у меня глюк — не могу добавить в избранное твое сообщение?
[]
>>> Может я чего-то не допонял, но каким образом мне это поможет? Я же не кидаю исключение руками, оно генерится программой неизвестно где и почему (известен только блок кода). > > ME>Исходники тебе доступны? > > Да, доступны.
Ты можешь подключить во все исходники хедер с тем кодом и перед catch(...) добавить catch(throw_site&) ?
Awaken wrote:
> > L>Может я чего-то не допонял, но каким образом мне это поможет? Я же не кидаю исключение руками, оно генерится программой неизвестно где >и почему (известен только блок кода). > > определить тип исключения программно в рантайме можно только если есть предположения о его типе > тогда ставим несколько catch-ей для каждого предполагаемого базового класса исключения
> В какой из блоков мы прилетим, и зависит ли это от порядка баз и от порядка блоков?
Сначала показалось, что это один из темных углов С++, а ответ-то простой — прилетим в в the_exception. Там ведь ищется не наиболее подходящий обработчик, а первый подходящий.
[]
> Сначала показалось, что это один из темных углов С++, а ответ-то простой — прилетим в в the_exception. Там ведь ищется не наиболее подходящий обработчик, а первый подходящий.
Здравствуйте, Linuxoid, Вы писали:
L>Здравствуйте, bkat, Вы писали:
B>>Здравствуйте, Linuxoid, Вы писали:
B>>В VS 6.0 такая возможность тоже есть.
L>Этот метод подойдет для сервиса, работающего в real-time ?
bkat, прости что вмешиваюсь в вашу переписку =)
метод подойдёт. Если исключение генерится в процессе работы сервиса (при возникновении какого-то внешнего воздействия), то коннекться к процессу дебаггером и делай как bkat написал
Если исключение генерится в самом начале работы сервиса (при его загрузке), то есть два пути
1) тебе доступны исходники сервиса. Вставляешь участок кода __asm int 3 в ServiceMain
2) тебе недоступны исходники сервиса. Или идея с int 3 не нравится. Тогда открываем реестр
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\my_service.exe]
"Debugger"="D:\\dbg\\vs7jit.exe"
Естественно, в качестве поля Debugger прописываешь свой путь к нужному файлу. На это поле есть ограничение — насколько помню, длина строки не должна быть больше 24 или 26 символов. В общем, стандартный путь в папку Visual Studio не подходит. Так что копируй файлы, требуемые для дебаггера (вместе с dll) куда-нибудь в корень.
Для 6й студии дебаггер msdev.exe
Далее открываешь services.msc , находишь в нём нужный сервис, Properties, в закладке Log On выставляешь ему галочку Allow service to interact with desktop
запускаешь сервис. Дебаггер должен подцепиться к нему автоматически.
Здравствуйте, MaximE, Вы писали:
ME>Linuxoid wrote:
ME>[]
>>>> Может я чего-то не допонял, но каким образом мне это поможет? Я же не кидаю исключение руками, оно генерится программой неизвестно где и почему (известен только блок кода). >> >> ME>Исходники тебе доступны? >> >> Да, доступны.
ME>Ты можешь подключить во все исходники хедер с тем кодом и перед catch(...) добавить catch(throw_site&) ?
Подключил, проверил. Я же говорил что не поможет Программа проскакивает catch (exception& e) и сваливается в catch(...) Максим, мне кажется вы не совсем поняли суть проблемы. Еще раз хочу подчеркнуть, что приложение явно (т.е. с помощью throw) исключение не кидает, поэтому переопределение задачу не решает.
Linuxoid wrote:
> Подключил, проверил. Я же говорил что не поможет Программа проскакивает catch (exception& e) и сваливается в catch(...) Максим, мне кажется вы не совсем поняли суть проблемы. Еще раз хочу подчеркнуть, что приложение явно (т.е. с помощью throw) исключение не кидает, поэтому переопределение задачу не решает.
ME>(Что-то подсказывает, что сервис твой виндозный, так как в Linux сигналы в catch(...) никак не попадают)
Сервис действительно виндовый (под линухом такие штуки называются демонами )
Уже нашел. Сваливается на макросе BREAK() (который разворачивается в debug-версии в _asm int 3). Кстати хотелось бы узнать подробнее про int 3. Я так понимаю это отладочное прерывание, по которому должна выполняться остановка в отладчике? А почему тогда возникают такие проблемы?
ME>>(Что-то подсказывает, что сервис твой виндозный, так как в Linux сигналы в catch(...) никак не попадают)
L>Сервис действительно виндовый (под линухом такие штуки называются демонами ) L>Уже нашел. Сваливается на макросе BREAK() (который разворачивается в debug-версии в _asm int 3). Кстати хотелось бы узнать подробнее про int 3. Я так понимаю это отладочное прерывание, по которому должна выполняться остановка в отладчике? А почему тогда возникают такие проблемы?
Ну BREAK() в исходнике поставлен для каких-то целей, например не прошла проверка и нужно попасть в отладчик, так посмотри почему твой код попадает в BREAK().
Здравствуйте, Linuxoid, Вы писали:
L>Уже нашел. Сваливается на макросе BREAK() (который разворачивается в debug-версии в _asm int 3). Кстати хотелось бы узнать подробнее про int 3. Я так понимаю это отладочное прерывание, по которому должна выполняться остановка в отладчике?
Именно так.
Дебаггер замещает код в точках остановок на инструкцию int 3. Когда вызывается обработчик, то дебаггер смотрит в свою таблицу, является ли это точкой остановки, или это авторство исходной программы.
L>А почему тогда возникают такие проблемы?
Потому что если дебаггера (и, соответственно, осмысленного обработчика) нет, то дефолтный обработчик выполняет какое-то ритуальное действие — например, raise(SIGINT) или что-нибудь в таком роде.
Здравствуйте, MaximE, Вы писали:
ME>Костя Ещенко wrote:
ME>[]
>> Сначала показалось, что это один из темных углов С++, а ответ-то простой — прилетим в в the_exception. Там ведь ищется не наиболее подходящий обработчик, а первый подходящий.
ME>Воистину так
Здравствуйте, MaximE, Вы писали:
ME>Linuxoid wrote:
>> Есть блок кода, в котором возникает исключение (довольно большой). Блок защищен оператором try, исключение перехватывается в catch(...) (других catch нет). Неизвестно что вызывает исключение и в каком конкретно месте оно возникает. Как получить более подробную информацию и локализовать проблемное место?
ME>Если сорс код доступен, то переносимый способ — это задефайнить throw:
ME>
Объясните плз,почему я не могу получить информацию из std::exception& e , почему выводится пустая строка,а не oops . Спасибо.
ME>-- ME>Maxim Yegorushkin
"Если вы держите слона за заднюю ногу, а он вырывается, то самое лучшее отпустить его" — Авраам Линкольн
Premature optimization is the root of all evil in programming. Donald Knuth
Здравствуйте, MaximE, Вы писали:
ME>pigeon wrote:
>> Объясните плз,почему я не могу получить информацию из std::exception& e , почему выводится пустая строка,а не oops . Спасибо.
ME>Не могу объяснить. Возможно, у тебя при компиляции отключены исключения.
Да нет,не отключены — имя файла и номер строки выводит,а вот причину ME>-- ME>Maxim Yegorushkin
"Если вы держите слона за заднюю ногу, а он вырывается, то самое лучшее отпустить его" — Авраам Линкольн
Premature optimization is the root of all evil in programming. Donald Knuth
pigeon wrote:
> ME>Не могу объяснить. Возможно, у тебя при компиляции отключены исключения. > Да нет,не отключены — имя файла и номер строки выводит,а вот причину
Посмотри в хедере, какой тип возвращаемого значения what(), вдруг он не char const*...
Здравствуйте, MaximE, Вы писали:
ME>pigeon wrote:
>> ME>Не могу объяснить. Возможно, у тебя при компиляции отключены исключения. >> Да нет,не отключены — имя файла и номер строки выводит,а вот причину
ME>Посмотри в хедере, какой тип возвращаемого значения what(), вдруг он не char const*...
typedef const char *__exString;
проверил на gcc все нормально работает,может это проблема в VC++ 6 или в родном STL .
В любом случае спасибо.
ME>-- ME>Maxim Yegorushkin
"Если вы держите слона за заднюю ногу, а он вырывается, то самое лучшее отпустить его" — Авраам Линкольн
Premature optimization is the root of all evil in programming. Donald Knuth
Здравствуйте, MaximE, Вы писали:
ME>Если сорс код доступен, то переносимый способ — это задефайнить throw:
Отличный способ! Но возникает одна сложность — как быть с throw в спецификациях исключений? Там он заменяется препроцессором в совершенно неудобоваримую конструкцию...
Здравствуйте, TheIrix, Вы писали:
TI>Здравствуйте, MaximE, Вы писали:
ME>>Если сорс код доступен, то переносимый способ — это задефайнить throw:
TI>Отличный способ! Но возникает одна сложность — как быть с throw в спецификациях исключений? Там он заменяется препроцессором в совершенно неудобоваримую конструкцию...
+1
В большинстве мест можно спецификацию исключений закомментировать, а не ждать пока ваш любимый компилятор начнёт вызывать terminate()
А если где очень надо, то можно сделать #undef. Не очень красиво конечно, но что делать.
Можно оформить в виде:
Здравствуйте, Linuxoid, Вы писали:
L>Есть блок кода, в котором возникает исключение (довольно большой). Блок защищен оператором try, исключение перехватывается в catch(...) (других catch нет). Неизвестно что вызывает исключение и в каком конкретно месте оно возникает. Как получить более подробную информацию и локализовать проблемное место?
Радикальный вариант! Код программы не надо трогать совсем!
Если на платформе Win32... Хотя на Win32 не может работать real-time ПО... Но всё же почти real-time может. Хотя на других не совсем убогих платформах должны быть аналогичные средства... Whatever
Делаешь небольшую консольную прогу Х, которая стартует вместе с твоим сервисом.
Х подрубается как отладчик к сервису с помощью DebugActiveProcess()
Х ждёт отладочных сообщений от сервиса с помощью WaitForDebugEvent()
Х при поступлении EXCEPTION_DEBUG_EVENT при помощи библиотечки DbgHelp функцией SymFromAddr() по адресу находит имя функции, которая кинула исключение.
Х пишет время, информацию об исключении, имя функции в файлик.
Задача решена
Получается такой мини-отладчик для специфичной цели логирования исключений. Если кидается не в твоей функции, а в библиотечной, то можно какой-нибудь другой инфы нарыть вместо имени функции, хотя, например, msvcrt тоже с pdb'шкой поставляется.
Здравствуйте, remark, Вы писали:
R>Делаешь небольшую консольную прогу Х, которая стартует вместе с твоим сервисом. R>Х подрубается как отладчик к сервису с помощью DebugActiveProcess()
Не будет работать под ограниченным пользователем. А требовать для работы программы админских прав — дурной тон.
Здравствуйте, Centaur, Вы писали:
C>Здравствуйте, remark, Вы писали:
R>>Делаешь небольшую консольную прогу Х, которая стартует вместе с твоим сервисом. R>>Х подрубается как отладчик к сервису с помощью DebugActiveProcess()
C>Не будет работать под ограниченным пользователем. А требовать для работы программы админских прав — дурной тон.
А real-time сервис устанавливает и настраивает юзер?
Здравствуйте, remark, Вы писали:
R>>>Делаешь небольшую консольную прогу Х, которая стартует вместе с твоим сервисом. R>>>Х подрубается как отладчик к сервису с помощью DebugActiveProcess()
C>>Не будет работать под ограниченным пользователем. А требовать для работы программы админских прав — дурной тон.
R>А real-time сервис устанавливает и настраивает юзер?
В любом случае, если мы запускаем отдельный служебный процесс, то ничто нам не мешает унести в него глючный падучий код и обрабатывать уже не смертельный UB у себя в кишках, а всего лишь ненормальное завершение дочернего процесса.
TheIrix wrote:
> Здравствуйте, MaximE, Вы писали: > > ME>Если сорс код доступен, то переносимый способ — это задефайнить throw: > > Отличный способ! Но возникает одна сложность — как быть с throw в > спецификациях исключений? Там он заменяется препроцессором в совершенно > неудобоваримую конструкцию...
Согласен, способ не без изъяна.
catch(...) { throw; }
Также не будет компилироваться.
-- Maxim Yegorushkin
No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Здравствуйте, Linuxoid, Вы писали:
L>Есть блок кода, в котором возникает исключение (довольно большой). Блок защищен оператором try, исключение перехватывается в catch(...) (других catch нет). Неизвестно что вызывает исключение и в каком конкретно месте оно возникает. Как получить более подробную информацию и локализовать проблемное место?
Раз уж поднялась эта тема, то вот интересная ссылка про то как можно в дебагере под виндой опредедить колстэк на момент исключения.
Здравствуйте, MaximE, Вы писали:
ME>Согласен, способ не без изъяна.
ME>
ME>catch(...) { throw; }
ME>
ME>Также не будет компилироваться.
Увы, да... Спецификации исключений встречаются только в библиотечном коде (stl, boost), и можно (как показано выше) раздефайнить throw.
А вот "throw;"... Даже не знаю, можно ли написать корректный по отношению к этим случаям макрос...