исключения и библиотеки (C++)
Написал бы, что за исключение.
Вопрос: значит ли это, что исключение возникло в библиотеке?Если библиотека кидает исключения, то это признак полной задницы в архитектуре. Я бы очень наказал того кто это делает, и отказался от использования такой библиотеки.
Библиотека не имеет права кидать исключения. Все ошибки — только по возврату.
ЗЫ: Я не имел в виду библиотеки типа набора шаблонных классов, как STL. Я имел в виду бинарные библиотеки, которые могли быть скомпилированы другим компилятором (версией и потому метод обработки исключений может привести к фатальностям.
Ведь если исключение не перехватывается в самом приложении, то по идее окошко это выскочить должно.
Окошка никакого не бывает, бывает остановка по 6 сигналу. Это в юниксовых, в винде наверное, да, окошко...
Или, скажем, нужно использовать __try __except?а что это за хрень?
Коллега, если ты пишешь на плюсах, пиши кросплатформенно, или пиши на своем до-диезе.
а что это за хрень?Это - микрософтовая хрень для отлова исключений Win32. для С.
Я бы на твоем месте попытался бы
1. отловить стек при убиваии приложения (terminate exit abort, ...)
2. отловить стек при записи сообщения в лог (надо смотреть, какое там у винды api для работы с eventlog'ом)
ну а дальше отлаживаться и думать
Это - микрософтовая хрень для отлова исключений Win32. для С.в смысле, для C++?
The try-except statement is a Microsoft extension to the C language that enables applications to gain control of a program when events that normally terminate execution occur. Such events are called exceptions, and the mechanism that deals with exceptions is called structured exception handling.Хотя в С++ тоже
Exceptions can be either hardware- or software-based. Even when applications cannot completely recover from hardware or software exceptions, structured exception handling makes it possible to display error information and trap the internal state of the application to help diagnose the problem. This is especially useful for intermittent problems that cannot be reproduced easily.
В лог пишется вот что:
Event Type: Error
Event Source: COM+
Event Category: SVC
Event ID: 4194
Date: 18.07.2008
Time: 15:40:29
User: N/A
Computer: CCAPPCORP
Description:
The system has called a custom component and that component has failed and generated an exception. This indicates a problem with the custom component. Notify the developer of this component that a failure has occurred and provide them with the information below.
Component Prog ID: SC.Pool 4 4
Method Name: IDispenserDriver::AddRef
Process Name: hdx_dc.exe
The serious nature of this error has caused the process to terminate.
Exception: C0000005
Address: 0x7878F3A2
Call Stack:
comsvcs!DispManGetContext(unsigned long *,unsigned long *) + 0x992
comsvcs!DispManGetContext(unsigned long *,unsigned long *) + 0x2181
и за ним:
Event Type: Error
Event Source: COM+
Event Category: SVC
Event ID: 4097
Date: 18.07.2008
Time: 15:40:29
User: N/A
Computer: CCAPPCORP
Description:
The run-time environment has detected an inconsistency in its internal state. Please contact Microsoft Product Support Services to report this error. *** Error in __FILE__(926): Application image dump failed.
EXCEPTION_ACCESS_VIOLATION - это к SEH относится, ловится __except'ом
зы
использование catch(...) - зло
код, ловящий AV - еще большее зло (кроме некоторых очень специфичных исключений)
The system has called a custom component and that component has failed and generated an exception
вы что, пишете комовские объекты, или библиотеки юзаете комовские ?
м.б. в одном из ваших комовских интрефейсных методов наружу вылетает AV ?
Если так, то не исключено , что некий код (некой библиотеки или системный, комовский) это исключение поймает (потому что там стоит catch(... запишет в лог и прибьет процесс, короче симптомы будут такие, как у тебя.
под виндой (во всяком случае после майкросовтофского компялтора (ну и для точности, под шестой студией - более позних я не пробовал) прекрасно поймается и с помощью catch(...)Сейчас SEH ловится только если включена специальная опция. Но я не знаю таких идиотов, которые её сейчас включают.
Что касается темы, то там по всей видимости используется COM объект, который уже удалён. Видимо, кто-то забыл написать AddRef или неправильно назвал однопоточный КОМпонент многопоточным. Смысла ловить этот SEH в общем-то нет, после него всё равно придётся упасть.
Окошко программа не выводит, потому что кто-то инсталлировал SEH Handler, вызовы SetErrorMode, SetUnhandledExceptionFilter. SEH Handler записывает информацию о падении, сохраняет краш дампы, пишет лог и убивает программу. Скорее всего, это делает правильно настроенный стандартный механизм КОМов или механизм обработки ошибок в винде.
В любом случае можно поставить свой SEH Handler и упасть оттуда с сохранением краш дампа.
таки мир становится лучше (давно не прогал под винду)
> то касается темы, то там по всей видимости используется COM объект, который уже удалён. Видимо, кто-то забыл
> написать AddRef или неправильно назвал однопоточный КОМпонент многопоточным.
мне кажется, скорее второе (или еще какой-то косяк многопоточности т.к. иначе падения были бы регулярными
мне кажется, скорее второе (или еще какой-то косяк многопоточности т.к. иначе падения были бы регулярнымине, гоню, очень может быть, что банально и AddRef забыт, там же AV, мб в редких случаях страница системе успевает отдаться....
банально и AddRef забыта его вообще можно случайно забыть, юзая компоинтеры (или как там оно называется)?
можно, если смешивать CComPtr и голые указатели (а голыми указателями как минимум в параметрах и возвращаемых значениях комовских методов надо пользоваться например, надо не забывать в правильных местах Detach юзать (а то как раз лишний Release будет вызван)
Если так, то не исключено , что некий код (некой библиотеки или системный, комовский) это исключение поймает (потому что там стоит catch(... запишет в лог и прибьет процесс, короче симптомы будут такие, как у тебя.Ну вот похоже оно и происходит. Лично я комовские объекты не исполдьзую. Скорее всего их юзает библиотека (сорсов и детального описания ее у меня нет).
А если так - то есть какой-нибудь способ? Сделать так, чтобы процесс не прибивался.
А если так - то есть какой-нибудь способ? Сделать так, чтобы процесс не прибивался.Я же уже написал: SetErrorMode, SetUnhandledExceptionFilter. Дальше обрабатываешь SEH, двигаешь PI на другую команду и продолжаешь выполнение. Но смысла в этом почти наверняка не будет.
Я же уже написал: SetErrorMode, SetUnhandledExceptionFilter. Дальше обрабатываешь SEH, двигаешь PI на другую команду и продолжаешь выполнение. Но смысла в этом почти наверняка не будет.упс
не до конца прочитала ответ
пасиб!
попробую...
Дальше обрабатываешь SEH, двигаешь PI на другую команду и продолжаешь выполнениеоооооооо, ну ты жесткий чувак
и это только для того (как я понял) заткнуть багу (или некорректное использование) библиотеки...
мне тут конечно подсказывают, что ты стебешся , но я все равно не могу удержаться
чтобы продвинуть EIP, нужно как минимум узнать длину текущей команды, а это правильно сделать ой как не просто
Я так и представил себе бедного (начинающего?) программиста(у пытающегося проделать (и отладить!) такой трюк
Спросили бы меня "что делать?", я бы сказал, чтобы сохранили краш дамп и посмотрели стек. А потом по обстоятельствам либо править свой код, либо искать поставщика КОМпонента.
двигать указатели - в сад, в сад.
чтобы продвинуть EIP, нужно как минимум узнать длину текущей команды, а это правильно сделать ой как не простоэтого разве в seh-е нет?
но вряд-ли (да из инфы там по-моему 1 или 2 DWORD'а, ну в общем мало т.к. бессмысленно делать что-либо после AV, отличное от убивания приложения. Во всяком случае в линуксе прямо заявлено, что если обработчик хардварных сигналов (сегфолт, например) возвращает управление, то что дальше будет - зависит от реализации, напрмер, система сама может убить процесс.
да из инфы там по-моему 1 или 2 DWORD'а, ну в общем малоинфы, там до хрена. как минимум состояния всех регистров - включая mmx и fpu
зы
посмотрел.
да, адреса следующей команды к сожалению там нет.
EXCEPTION_DISPOSITION
__cdecl _except_handler(
struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * DispatcherContext
);
в том числе struct _CONTEXT
причем прикольно в винде, контекст можно ручками подхачить(возможно, что даже eip можно подменить) и сказать "теперь все ОК, продолжай выполнение", прикол...
и сказать "теперь все ОК, продолжай выполнение"Думаешь, как On Error Resume Next работает?
на http://www.wasm.ru/article.php?article=Win32SEHPietrek1
сказано, что такой код работает (я конечно сам не проверял..., но думаю, что там вряд ли обманывают )
EXCEPTION_DISPOSITION
__cdecl
_except_handler(
struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * DispatcherContext )
{
unsigned i;
// Сообщаем, что сработал наш обработчик исключений.
printf( "Hello from an exception handler!\n" );
// Изменяем значение регистра EAX в context record таким образом, чтобы оно
// указывало на какое-либо, доступное для записи место в памяти.
ContextRecord->Eax = (DWORD)&scratch;
// Просим ОС еще раз попытаться выполнить вызвавшую исключение инструкцию.
return ExceptionContinueExecution;
}
не понял о чем тыв Visual Basic есть такой вариант обработки ошибок - забивать на них и идти далее выполнять прогу.
причем прикольно в винде, контекст можно ручками подхачить(возможно, что даже eip можно подменить) и сказать "теперь все ОК, продолжай выполнение", прикол...а что, у нас так завершают подвисшие регрешнтесты... Правда, выполнение этого в отладчике, как правило, приводит к вываливанию приложения. А так, если дело идёт к завершению приложения, а какой-то поток подвис (если это, конечно, не связано с каким-то вводом-выводом то изменив EIP можно попытаться корректно освободить потоко-зависимые ресурсы (если в этом есть какой-либо смысл).
Оставить комментарий
biven10
Ребят, а вот такой вопрос.Есть приложение, вызывающее пару библиотек. Все на плюсах.
И вот очень редко приложение обваливается. При этом в eventlog пишется сообщение о возникшем исключении, но стандартное ошибочное окно не выскакивает (в котором еще предлагают либо отладить приложение, либо закрыть его).
Вопрос: значит ли это, что исключение возникло в библиотеке? Ведь если исключение не перехватывается в самом приложении, то по идее окошко это выскочить должно.
И еще - если, допустим, исключение возникло в библиотеке, то обязано ли приложение перехватить его методом catch (....) ?
Или, скажем, нужно использовать __try __except?