Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> SEH 
:(
    Опции темы
FCM
Дата 20.8.2009, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: нет
Всего: 9



Спасибо за ответы.
Цитата(GremlinProg @  19.8.2009,  10:55 Найти цитируемый пост)
ну так проверка на выход за границы массива только в дебаге 

Я имел в виду, почему такое исключение заявлено (в книге), но не отлавливается, написанной от руки SEH-ловушкой с EXCEPTION_ARRAY_BOUNDS_EXCEEDED .

А есть ли разница между CRT и C++ RTL?
_RTC_Initialize - это инициализация CRT?
(Например, Visual Fortran при компоновке своих приложений использует стартовые функции CRT и SEH-обработчик с _XcptFilter, но он же не должен пользоваться С++ RTL?)

Рихтер пишет про _CppUnhandledExceptionHandler (для последней "обработки" стандартных С++ исключений до "глобального" для данного потока UnhandledExceptionHandler ). Однако в crt0.c или в crtexe.c есть _XcptFilter, а _CppUnhandledExceptionHandler  нет, а в 
в crtdll.c. есть _CppUnhandledExceptionHandler  но нет _XcptFilter. Как же реально это выглядит после компоновки приложения? Охватывает ли SEH c _CppUnhandledExceptionHandler SEH c _XcptFilter?

Еще есть вопрос по функции _matherr , которая , будучи определенной пользователем в исходнике с программой, сама проявляет себя в некоторых критических ситауциях - как ей это удается, с помощью того же SEH или по-другому?
(Связано ли это как-то с тем, что объявление  _matherr содержится в crtexe.c )

PM MAIL   Вверх
GremlinProg
Дата 20.8.2009, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(FCM @  20.8.2009,  13:05 Найти цитируемый пост)
Я имел в виду, почему такое исключение заявлено (в книге), но не отлавливается, написанной от руки SEH-ловушкой с EXCEPTION_ARRAY_BOUNDS_EXCEEDED 

проблема отлова такого исключения в том, что при затирании окружения массива может затереться сама запись SEH, она же находится так же, в стеке, просто чуть выше самого массива, поэтому будет довольно рисковано пытаться пройти по адресу этого обработчика

Цитата(FCM @  20.8.2009,  13:05 Найти цитируемый пост)
_RTC_Initialize - это инициализация CRT?

это скорее всего инициализация счетчиков ошибок времени исполнения (RTC - Run-Time Error Checking): http://msdn.microsoft.com/en-us/library/w68b74dy.aspx

CRT - изначально к С++ не относится ( C run-time library (without iostream or standard C++ library) ): http://msdn.microsoft.com/en-us/library/abx4dbyh.aspx

_CppUnhandledExceptionHandler - это я так понимаю встроенный обработчик от MSVC,
для фортрана может быть свой обработчик: названия могут различаться, это же просто callback, который регистрируется через SetUnhandledExceptionFilter
Цитата(FCM @  20.8.2009,  13:05 Найти цитируемый пост)
Охватывает ли SEH c _CppUnhandledExceptionHandler SEH c _XcptFilter?

а какая разница?
это же по сути - финальный фильтр исключений,
если его не ставить, то будет работать встроенный UnhandledExceptionFilter, который уже покажет окно с ошибкой с возможностью дальнейшей отладки приложения встроенным отладчиком (правда это можно перекрыть, выставив SEM_NOGPFAULTERRORBOX).
Цитата(FCM @  20.8.2009,  13:05 Найти цитируемый пост)
Еще есть вопрос по функции _matherr , которая , будучи определенной пользователем в исходнике с программой, сама проявляет себя в некоторых критических ситауциях - как ей это удается, с помощью того же SEH или по-другому?

Цитата

The _matherr function processes errors generated by the floating-point functions of the math library. 

ну тут вариантов не так много, конечно SEH,
только она не будет работать, если маскировать контрольное слово FPU-исключений, но это в принципе и так понятно
Цитата(FCM @  20.8.2009,  13:05 Найти цитируемый пост)
Связано ли это как-то с тем, что объявление  _matherr содержится в crtexe.c

да, отчасти:
Цитата

For special error handling, you can provide a different definition of _matherr. If you use the dynamically linked version of the C run-time library (Msvcr90.dll), you can replace the default _matherr routine in a client executable with a user-defined version. However, you cannot replace the default _matherr routine in a DLL client of Msvcr90.dll.

т.е. пользовательский  _matherr перекрывает встроенный,
а встроенный, по-идее, должен просто возвращать 0, т.е. разрешить отображать окно с fpu-ошибкой,

достаточно поставить в самом верху один SEH-фрейм на эти 6 исключений и всегда вызывать _matherr, независимо от того, пользовательская она или встроенная,
т.е. без лишних наворотов с регистрацией обработчика реализуется FPU-сторож


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
FCM
Дата 21.8.2009, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: нет
Всего: 9



Я тут попробовал в одной программе, где просто просматривал статусное слово при FLT-операциях, менять контрольное слово (отключать FPU "обработку" тех или иных FLT-ошибок) и ловить и диагностировать их с помощью  SEH. 
Обнаружилась странная штука:  если в ходе операции возникает одно исключение (например FLT_DIVIDE_BY_ZERO), то ловится все отлично, но если операция сопровождается 2-мя исключениями (например, при (упрощенный фрагмент)
Код

...
_controlfp( _EM_DEFAULT - _EM_OVERFLOW- _EM_INEXACT, _MCW_EM );
__try { 
  double  d = 1.e100; 
  float      r = d;
}
__except(1) { cout << GetExceptionCode() << endl;}
...

возникает Overflow и Inexact), 
то ситуация странная, с одной стороны, до внешних обрабочиков (которые останавливают программу при остутствии моего SEH) дело не доходит, но и мой обработчик тоже реально не выполняется - программа прекращает выполнение в месте возникновения исключения.
Я пробовал вложенные обработчики с фильтрами, настроенными непосредственно на вышеуказанные исключения - тоже не попадаю в тело обработчика и не получаю окошко от внешних (финальных) обработчиков (- программа прекращает выполнение в месте возникновения исключения.).



Это сообщение отредактировал(а) FCM - 21.8.2009, 12:04
PM MAIL   Вверх
GremlinProg
Дата 21.8.2009, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(FCM @  21.8.2009,  13:58 Найти цитируемый пост)
_controlfp( _EM_DEFAULT - _EM_OVERFLOW- _EM_INEXACT , _MCW_EM);

этого кода я не понял,
если ты хотел включить какое-то исключение, то во втором параметре нужно использовать не арифметические, а побитовые операции:
Код

unsigned int ctrl;
__try{
    _controlfp_s( &ctrl, 0, 0 );
    _controlfp_s( &ctrl, ctrl & ~_EM_OVERFLOW, _MCW_EM );
    double d    = 1.e100; 
    float r    = (float)d;
}
__except( EXCEPTION_EXECUTE_HANDLER ){
    ::MessageBox(0,0,0,0);
}

вот так я четко размаскировал только одно исключение, не затронув остальные,
т.е. включил SEH только для _EM_OVERFLOW
можешь проверить
ps: _controlfp_s( &ctrl, 0, 0 )  вернет текущее слово управления FPU

Это сообщение отредактировал(а) GremlinProg - 21.8.2009, 12:41


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 21.8.2009, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



для включения сразу нескольких исключений все аналолгично:
Код

_controlfp_s( &ctrl, ctrl & ~( _EM_OVERFLOW | _EM_INEXACT ), _MCW_EM );



--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
FCM
Дата 21.8.2009, 17:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: нет
Всего: 9



Цитата(GremlinProg @  21.8.2009,  12:37 Найти цитируемый пост)
_controlfp( _EM_DEFAULT - _EM_OVERFLOW- _EM_INEXACT , _MCW_EM);

этого кода я не понял,


Там у меня опечатка (вследствие упрощения исходного текста)- должно быть
int ctrl = _controlfp( _CW_DEFAULT - _EM_OVERFLOW- _EM_INEXACT , _MCW_EM); 
где _CW_DEFAULT  согласно float.h равен сумме кодов fp-исключений и кое-чего еще
Код

#define _CW_DEFAULT   ( _RC_NEAR + _PC_53 + _EM_INVALID + _EM_ZERODIVIDE + _EM_OVERFLOW + _EM_UNDERFLOW + _EM_INEXACT + _EM_DENORMAL)

Поэтому записи вида
_CW_DEFAULT-_EM_OVERFLOW  или
_CW_DEFAULT-_EM_OVERFLOW - _EM_INEXACT 
в функции _controlfp в принципе корректны (им наплевать на текущее контрольное слово они берут максимальную маску и отнимают код(ы) исключения, которое FPU должен сгенерить),  хотя менее професcиональны чем побитовый вариант.
В любом случае я просматриваю контрольное слово в двоичном формате и вижу, что сработало. 
Вопрос был немного в другом.
в ходе операции 
 float      r = d;
возникает два исключения OVERFLOW и INEXACT (я их виже просматривая статусное слово) и мой пользовательский SEH-обработчик не может сам  полноценно ухватить это "двойное" исключение, и кроме того мешает внешним SEН обработчикам (от OC) вывести соотв. окошко (с кодом зафиксированного исключения). ( Или это фокусы компилятора MSVC7?).
 

PM MAIL   Вверх
GremlinProg
Дата 21.8.2009, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(FCM @  21.8.2009,  19:38 Найти цитируемый пост)
Вопрос был немного в другом.в ходе операции  float      r = d;возникает два исключения OVERFLOW и INEXACT (я их виже просматривая статусное слово) и мой пользовательский SEH-обработчик не может сам  полноценно ухватить это "двойное" исключение, и кроме того мешает внешним SEН обработчикам (от OC) вывести соотв. окошко (с кодом зафиксированного исключения). ( Или это фокусы компилятора MSVC7?).

покажи содержимое регистра SR, т.к. я вупор не вижу двух одновременных исключений со всеми твоими параметрами,
статус XX88 задает поднятые: третий и седьмой биты регистра SR, которые говорят только о переполнении
(INEXACT - это пятый бит, нумерация бит - с нуля)


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
FCM
Дата 21.8.2009, 19:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: нет
Всего: 9



Как просмотреть регистр я не знаю.
Я вывожу текущее контрольное слово

до моих установок имею в двоичном формате
1001 0000 0000 0001 1111
после моих установок с изменением маски для Overflow и Inexact
1001 0000 0000 0001 1010

где
1000 0000 0000 0000 0000   -  denormal
                                 1 0000   -  invalid
                                    1000   -  zerodivide
                                      100   -  overflow
                                        10   -  underflow
                                          1   -  inexact
PM MAIL   Вверх
GremlinProg
Дата 21.8.2009, 20:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



контрольное слово вообще ни чего не говорит о произошедших исключениях,
ты в этом слове только маскируешь прерывания, которые должны произойти

реально, произощедшие исключения можно посмотреть в первых восьми битах слова статуса - SR

под отладчиком просто открой вкладку "регистры" и добавь к ним FPU
в MSVC соответствие регистров такое:
CR - это CTRL
SR - это STAT

вот в STAT и смотри


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
FCM
Дата 22.8.2009, 07:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: нет
Всего: 9



Забыл написать, что я и статусное слово тоже просматриваю (с помощью __statusfp) и вижу при вышеуказанных действиях:
101 (левые нулевые биты не отображаю)

В отладчике тоже посмотрю.
PM MAIL   Вверх
FCM
Дата 22.8.2009, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: нет
Всего: 9



1) Кажется я понял в чем дело.
Я запускал в Debug-сборке через Ctrl+F5 (запуск без отладки) и получал то, что получал.
Если я запускаю в Debug через F5, то попадаю в свои ловушки, а поскольку в них только вывожу информацию, то в итоге получаю в окошечке внизу :
First_chance exception и далее описание и код исключения.
В Releas'e попадаю в свои ловушки, как и должно быть.

Интересно, в чем фишка с Ctrl+F5 (запуск без отладки) - какие-то "подводные камни"?

2) Если открыть окошко Debug/Exceptions, то видим 4 или 5 (в МVС9) групп исключений. Последняя Win32 как я понимаю - аппаратные; одна(в МVС7)  или две (в МVС9) группы только для управляемого кода; одна группа для CRT ловушек.
А что значит группа для С++ исключений?:
_com_error
_ATL::CAtlException
CExeption
std::exception
void



Это сообщение отредактировал(а) FCM - 22.8.2009, 09:40
PM MAIL   Вверх
GremlinProg
Дата 22.8.2009, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



вот сейчас получил 2 ошибки одновременно, но эти 2 ошибки выставляются в статусе только если отключены исключения, стоит только включить SEH на обе, и статус начинает говорить нам только об одной ошибке - переполнение, т.е. ни каких программных проблем тут нет, просто видимо команда перестает выполняться при обнаружении первого немаскированного исключения

включи в CR только _EM_INEXACT и получишь оба флага поднятых ( _EM_OVERFLOW и _EM_INEXACT )

но бросается конечно же только одно исключение, для которого оно разрешено

суть видимо в том, что первое действие fstp - это все же загрузка регистра, а уже второе - проверка его содержимого на точность

Добавлено через 8 минут и 57 секунд
Цитата(FCM @  22.8.2009,  11:38 Найти цитируемый пост)
Я запускал в Debug-сборке через Ctrl+F5 (запуск без отладки) и получал то, что получал.Если я запускаю в Debug через F5, то попадаю в свои ловушки, а поскольку в них только вывожу информацию, то в итоге получаю в окошечке внизу

ну так, естественно, Ctrl+F5 независимо от сборки, не подключает отладчик к процессу вообще

Цитата(FCM @  22.8.2009,  11:38 Найти цитируемый пост)
 Последняя Win32 как я понимаю - аппаратные

последние - это как раз SEH исключения

Цитата(FCM @  22.8.2009,  11:38 Найти цитируемый пост)
А что значит группа для С++ исключений?

то же самое, что и все остальные - это окно позволяет приостанавливать отладчик, если генерируется какое-то из этих исключений,
на Release-сборку это не оказывает ни какого влияния (просто в дебаге удобно по-быстрому найти ошибку, не расставляя брейкпойнты)



--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GremlinProg
Дата 22.8.2009, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(GremlinProg @  22.8.2009,  11:42 Найти цитируемый пост)
на Release-сборку это не оказывает ни какого влияния

не оказывает ни какого влияния вообще на любую сборку, запущенного вне отладчика


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
FCM
Дата 23.8.2009, 08:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: нет
Всего: 9



Понятно, спасибо

А вот применение signal - это только для установки дополнительных "пунктов" для _XcptFilter?
Или что-то более универсальное?
PM MAIL   Вверх
GremlinProg
Дата 23.8.2009, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



в winxfltr.c описана реализация _XcptFilter и __CppXcptFilter
а в crtdll.c, dllcrt0.c, crtexe.c, crt0.c - их использование
разница между ними только в том, что __CppXcptFilter перехватывает только одно искусственное исключение 'msc'|0xE0000000, которое определяет С++ исключение с передачей в нем экземпляра класса (по сути - это враппер над _XcptFilter)
а _XcptFilter обрабатывает сразу серию исключений из _XcptActTab:
Код

const struct _XCPT_ACTION _XcptActTab[] = {

/*
 * Exceptions corresponding to the same signal (e.g., SIGFPE) must be grouped
 * together.
 *
 * If any XcptAction field is changed in this table, update the function
 * _initp_misc_winxfltr below. That field must be initialized with an
 * encoded function pointer at CRT initialization time.
 *
 *        XcptNum                                        SigNum    XcptAction
 *        -------------------------------------------------------------------
 */
        { (unsigned long)STATUS_ACCESS_VIOLATION,         SIGSEGV, SIG_DFL },

        { (unsigned long)STATUS_ILLEGAL_INSTRUCTION,      SIGILL,  SIG_DFL },

        { (unsigned long)STATUS_PRIVILEGED_INSTRUCTION,   SIGILL,  SIG_DFL },

/*      { (unsigned long)STATUS_NONCONTINUABLE_EXCEPTION, NOSIG,   SIG_DIE },
 */
/*      { (unsigned long)STATUS_INVALID_DISPOSITION,      NOSIG,   SIG_DIE },
 */
        { (unsigned long)STATUS_FLOAT_DENORMAL_OPERAND,   SIGFPE,  SIG_DFL },

        { (unsigned long)STATUS_FLOAT_DIVIDE_BY_ZERO,     SIGFPE,  SIG_DFL },

        { (unsigned long)STATUS_FLOAT_INEXACT_RESULT,     SIGFPE,  SIG_DFL },

        { (unsigned long)STATUS_FLOAT_INVALID_OPERATION,  SIGFPE,  SIG_DFL },

        { (unsigned long)STATUS_FLOAT_OVERFLOW,           SIGFPE,  SIG_DFL },

        { (unsigned long)STATUS_FLOAT_STACK_CHECK,        SIGFPE,  SIG_DFL },

        { (unsigned long)STATUS_FLOAT_UNDERFLOW,          SIGFPE,  SIG_DFL },

/*      { (unsigned long)STATUS_INTEGER_DIVIDE_BY_ZERO,   NOSIG,   SIG_DIE },
 */
/*      { (unsigned long)STATUS_STACK_OVERFLOW,           NOSIG,   SIG_DIE }
 */
};

вот по этой таблице и определяется, какой сигнал соответствует Win32-исключению

signal и raise - видимо, приближение к юниксам,
влияние signal может распространяться как на _XcptFilter, так и за его пределами (как например в abort)

в пределах _XcptFilter, signal позволяет разделить и переопределить его встроенное поведение

а все, что пропускает _XcptFilter идет уже на финальную обработку,
стоящую где-то на уровне создания процесса, т.е., скорее всего, где-то в недрах загрузчика

можно сказать, signal - универсальный обработчик исключений,
правда только их небольшого набора и не всегда именно через SEH


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0580 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.