Как поймать исключение типа Access Violation?
От: Аноним  
Дата: 25.10.06 12:44
Оценка:
Есть приложение (atl). Иногда в нём происходят различные исключения.
Идея простая: если приложение вылетает, то сделать запись в лог и ещё пару дел с доступными данными.

К сожалению, блок

try{
}
catch(...)
{
}


не помогает от Access Violation.

У кого-нить есть идеи, как решить такую проблему?
Re: Как поймать исключение типа Access Violation?
От: Константин Л. Франция  
Дата: 25.10.06 12:48
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Есть приложение (atl). Иногда в нём происходят различные исключения.

А>Идея простая: если приложение вылетает, то сделать запись в лог и ещё пару дел с доступными данными.

А>К сожалению, блок


А>
А>try{
А>}
А>catch(...)
А>{
А>}
А>


А>не помогает от Access Violation.


А>У кого-нить есть идеи, как решить такую проблему?


1. __try/__except
2. __set_se_translator
3. try/catch + /EHa

2 is more preferable
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Как поймать исключение типа Access Violation?
От: Аноним  
Дата: 26.10.06 12:03
Оценка: :))) :)))
Здравствуйте, Аноним, Вы писали:

>> Как поймать исключение типа Access Violation?


Очень просто!!!

int* p = 0;
*p = 2;

Re: Как поймать исключение типа Access Violation?
От: _vvs Россия  
Дата: 27.10.06 10:49
Оценка: -1
Здравствуйте, Аноним, Вы писали:

А>Есть приложение (atl). Иногда в нём происходят различные исключения.

А>Идея простая: если приложение вылетает, то сделать запись в лог и ещё пару дел с доступными данными.

А>К сожалению, блок


А>
А>try{
А>}
А>catch(...)
А>{
А>}
А>


А>не помогает от Access Violation.


А>У кого-нить есть идеи, как решить такую проблему?


Такого в работающей программе не должно быть. Вы обязательно должны отладить такие ошибки.
Если это происходит на вашей машине, то вы можете отладиться в отладчике. Иначе, есть два способа.
Либо пользоваться библиотеками, выводящими стек падения в аварийных случаях — типа dbghelp.dll
Либо смотреть дамп Dr.Watson'a с помощью WinDbg (нужны будут бинарники и pdb'шки приложения)
Re[2]: Как поймать исключение типа Access Violation?
От: alexeiz  
Дата: 29.10.06 07:09
Оценка: 1 (1)
Здравствуйте, Константин Л., Вы писали:

КЛ>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 компилятор не может выполнить многих оптимизаций, так как он предпологает, что исключение может произойти практически в любом месте программы.
Re: Как поймать исключение типа Access Violation?
От: trophim Россия  
Дата: 29.10.06 17:01
Оценка: -1
Здравствуйте, <Аноним>, Вы писали:

А>Есть приложение (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?
От: Константин Л. Франция  
Дата: 29.10.06 20:55
Оценка:
Здравствуйте, 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?
От: trophim Россия  
Дата: 29.10.06 20:58
Оценка:
Чего я наврал? Совсем всё???
[EOF]
Let it be! — Давайте есть пчелу!
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?
От: rm822 Россия  
Дата: 01.11.06 12:11
Оценка:
Здравствуйте, 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 дружит.
Работает с С++ исключениями это громко сказано, кто деструкторы вызывать будет?



<Аномим>Re[2]: Как поймать исключение типа Access Violation?
Автор:
Дата: 30.10.06

Написал что есть синхронная и асинхронная обработка исключений.
S — компилер считает что исключения генеряться только throw и может убить часть кода обработки если не видит никаких исключений
A — компилер считает что исключения может вызвать любой код.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Как поймать исключение типа Access Violation?
От: Sergey Россия  
Дата: 01.11.06 12:32
Оценка: 1 (1)
> 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?
От: trophim Россия  
Дата: 02.11.06 18:31
Оценка:
Здравствуйте, Sergey, Вы писали:

>> T>не ловит исключения нарушения доступа к памяти. Дело в том, что выражение catch(...) ловит любые исключения, которые принадлежат к С++ (!!! код у таких исключений, если вы помните == 0xe06d7363). А все другие пропускает мимо. У access violation exception код равен 0xC0000005.

>>
>> Неверно для MSVC. Catch(...) ловит все исключения без разбору потому как основаны на одном механизме

S>Не совем так. VC 6, 7, 7.1 ловили в catch(...) все SEH-based исключения. Однако VC 8 с опцией /EHsc ловит в catch(..) только плюсовые исключения. За другие опции не скажу, не проверял.


Вот, я ж говорил, что отцы поправят, если навру. Все. Пошли
[EOF]
Let it be! — Давайте есть пчелу!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.