Есть приложение (atl). Иногда в нём происходят различные исключения.
Идея простая: если приложение вылетает, то сделать запись в лог и ещё пару дел с доступными данными.
Здравствуйте, <Аноним>, Вы писали:
А>Есть приложение (atl). Иногда в нём происходят различные исключения. А>Идея простая: если приложение вылетает, то сделать запись в лог и ещё пару дел с доступными данными.
А>К сожалению, блок
А>
А>try{
А>}
А>catch(...)
А>{
А>}
А>
А>не помогает от Access Violation.
А>У кого-нить есть идеи, как решить такую проблему?
Здравствуйте, Аноним, Вы писали:
А>Есть приложение (atl). Иногда в нём происходят различные исключения. А>Идея простая: если приложение вылетает, то сделать запись в лог и ещё пару дел с доступными данными.
А>К сожалению, блок
А>
А>try{
А>}
А>catch(...)
А>{
А>}
А>
А>не помогает от Access Violation.
А>У кого-нить есть идеи, как решить такую проблему?
Такого в работающей программе не должно быть. Вы обязательно должны отладить такие ошибки.
Если это происходит на вашей машине, то вы можете отладиться в отладчике. Иначе, есть два способа.
Либо пользоваться библиотеками, выводящими стек падения в аварийных случаях — типа dbghelp.dll
Либо смотреть дамп Dr.Watson'a с помощью WinDbg (нужны будут бинарники и pdb'шки приложения)
Re[2]: Как поймать исключение типа Access Violation?
Здравствуйте, Константин Л., Вы писали:
КЛ>1. __try/__except КЛ>2. __set_se_translator КЛ>3. try/catch + /EHa
КЛ>2 is more preferable
В случае 2 тоже нужно использовать /EHa.
Выбор в общем случае зависит от того, чего ты хочешь достигнуть. Если хочешь прервать выполнение программы с сохранением текущего состояния в dump file, то здесь, конечно, предпочтительнее __try/__except + /EHcs. Ну а если хочешь поймать AV как C++-сное исключение, то __set_se_translator + /EHa.
Кстати, при /EHa компилятор не может выполнить многих оптимизаций, так как он предпологает, что исключение может произойти практически в любом месте программы.
Здравствуйте, <Аноним>, Вы писали:
А>Есть приложение (atl). Иногда в нём происходят различные исключения. А>Идея простая: если приложение вылетает, то сделать запись в лог и ещё пару дел с доступными данными.
А>К сожалению, блок
А>
А>try{
А>}
А>catch(...)
А>{
А>}
А>
А>не помогает от Access Violation.
А>У кого-нить есть идеи, как решить такую проблему?
Быстро и коротко об исключениях. C++ исключения базируются на SEH, т.е.,коротко говоря, на исключениях ОС. У всех исключений ОС есть свой уникальный код. (например, 0xC0000005 = Access Violation).
Как привинчивают C++ исключения к этому самому SEH? Каждый компилятор придумывает для исключений C++ уникальный код (например, VC 7.1 использует код 0xe06d7363; Borland Delphi 2006 — 0xEEDFADE; Borland C++ Builder 2006 — 0xEEDFAE6). Если RTL при помощи SEH ловит исключение и его код == тому самому уникальному коду (0xe06d7363), то это исключение считается пришедшим из C++. Используя дополнительные параметры, которыми снабжается исключение в момент его генерации, RTL может получить сылку на мнооого дополнительных сведений, как то класс исключения.
Таким образом: поймано исключение 0xe06d7363, извлекаем доп. сведения (класс исключения) и начинаем делать всякие специфичные для C++ stack unwinding etc.
Теперь очень просто понять почему код
try{
}
catch(...)
{
}
не ловит исключения нарушения доступа к памяти. Дело в том, что выражение catch(...) ловит любые исключения, которые принадлежат к С++ (!!! код у таких исключений, если вы помните == 0xe06d7363). А все другие пропускает мимо. У access violation exception код равен 0xC0000005.
Вот так все просто. Никакой магии.
А ловить AV, как уже сказали, можно при помощи __try {} __except... Такая штука работает не только с С++ исключениями. Она с AV дружит.
P.S. Если чего не так сказал, то "отцы" поправят.
[EOF]
Let it be! — Давайте есть пчелу!
Re[3]: Как поймать исключение типа Access Violation?
Здравствуйте, alexeiz, Вы писали:
A>Здравствуйте, Константин Л., Вы писали:
КЛ>>1. __try/__except КЛ>>2. __set_se_translator КЛ>>3. try/catch + /EHa
КЛ>>2 is more preferable
A>В случае 2 тоже нужно использовать /EHa.
Оказывается да. Интересно почему? При /EHsc SE тоже ловятся, но есть проблема с вызовом деструкторов локальных объектов.
[]
Re[2]: Как поймать исключение типа Access Violation?
Re[2]: Как поймать исключение типа Access Violation?
От:
Аноним
Дата:
29.10.06 23:46
Оценка:
все проще — ... в VC++ ловят AV. Фишка в том что если не указать /EHa то компилер волен не ставить SEH обработчик если он не видит throw между try и catch. memset(NULL,10,10); для него не является поводом поставить SEH frame. А вот throw либо вызов виртуального метода какого либо интерфейса с декларированным throw между try catch заставят ... ловить и AV . Такая вот нехитрая арифетика. Но это — implementation details. Правильно по любому юзать __try..__except а лучше — ставить Unhandler Exception Filter и в случае AV дампится, сохранять состояние и, в зависимости от необходимости — лапки кверху или саморестарт.
Re[2]: Как поймать исключение типа Access Violation?
Здравствуйте, trophim, Вы писали:
T>Здравствуйте, <Аноним>, Вы писали:
А>>Есть приложение (atl). Иногда в нём происходят различные исключения. А>>Идея простая: если приложение вылетает, то сделать запись в лог и ещё пару дел с доступными данными.
А>>К сожалению, блок
А>>
А>>try{
А>>}
А>>catch(...)
А>>{
А>>}
А>>
А>>не помогает от Access Violation.
А>>У кого-нить есть идеи, как решить такую проблему?
T>Быстро и коротко об исключениях. C++ исключения базируются на SEH, т.е.,коротко говоря, на исключениях ОС. У всех исключений ОС есть свой уникальный код. (например, 0xC0000005 = Access Violation).
Это под MSVC они базируются на SEH(что многократно описано) но они НЕ ОБЯЗАНЫ быть на этом основаны, компилер волен создать свой механизм
и было бы лучше если бы MSVC так и сделал, потому что ТОРМОЗИТ!
T>Как привинчивают C++ исключения к этому самому SEH? Каждый компилятор придумывает для исключений C++ уникальный код (например, VC 7.1 использует код 0xe06d7363; Borland Delphi 2006 — 0xEEDFADE; Borland C++ Builder 2006 — 0xEEDFAE6). Если RTL при помощи SEH ловит исключение и его код == тому самому уникальному коду (0xe06d7363), то это исключение считается пришедшим из C++. Используя дополнительные параметры, которыми снабжается исключение в момент его генерации, RTL может получить сылку на мнооого дополнительных сведений, как то класс исключения.
T>Таким образом: поймано исключение 0xe06d7363, извлекаем доп. сведения (класс исключения) и начинаем делать всякие специфичные для C++ stack unwinding etc.
На практике это так
T>Теперь очень просто понять почему код
T>
T>try{
T>}
T>catch(...)
T>{
T>}
T>
T>не ловит исключения нарушения доступа к памяти. Дело в том, что выражение catch(...) ловит любые исключения, которые принадлежат к С++ (!!! код у таких исключений, если вы помните == 0xe06d7363). А все другие пропускает мимо. У access violation exception код равен 0xC0000005.
Неверно для MSVC. Catch(...) ловит все исключения без разбору потому как основаны на одном механизме
T>Вот так все просто. Никакой магии. T>А ловить AV, как уже сказали, можно при помощи __try {} __except... Такая штука работает не только с С++ исключениями. Она с AV дружит.
Работает с С++ исключениями это громко сказано, кто деструкторы вызывать будет?
Написал что есть синхронная и асинхронная обработка исключений.
S — компилер считает что исключения генеряться только throw и может убить часть кода обработки если не видит никаких исключений
A — компилер считает что исключения может вызвать любой код.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Как поймать исключение типа Access Violation?
> T>не ловит исключения нарушения доступа к памяти. Дело в том, что выражение catch(...) ловит любые исключения, которые принадлежат к С++ (!!! код у таких исключений, если вы помните == 0xe06d7363). А все другие пропускает мимо. У access violation exception код равен 0xC0000005. > > Неверно для MSVC. Catch(...) ловит все исключения без разбору потому как основаны на одном механизме
Не совем так. VC 6, 7, 7.1 ловили в catch(...) все SEH-based исключения. Однако VC 8 с опцией /EHsc ловит в catch(..) только плюсовые исключения. За другие опции не скажу, не проверял.
Posted via RSDN NNTP Server 2.0
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[4]: Как поймать исключение типа Access Violation?
Здравствуйте, Sergey, Вы писали:
>> T>не ловит исключения нарушения доступа к памяти. Дело в том, что выражение catch(...) ловит любые исключения, которые принадлежат к С++ (!!! код у таких исключений, если вы помните == 0xe06d7363). А все другие пропускает мимо. У access violation exception код равен 0xC0000005. >> >> Неверно для MSVC. Catch(...) ловит все исключения без разбору потому как основаны на одном механизме
S>Не совем так. VC 6, 7, 7.1 ловили в catch(...) все SEH-based исключения. Однако VC 8 с опцией /EHsc ловит в catch(..) только плюсовые исключения. За другие опции не скажу, не проверял.
Вот, я ж говорил, что отцы поправят, если навру. Все. Пошли