Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > SEH


Автор: FCM 17.8.2009, 18:17
Почему-то с помощью SEH не удается отследить EXCEPTION_INT_OVERFLOW.
Не подавляется (обрабатывается) ли оно аппаратно?

Автор: GoldFinch 17.8.2009, 19:24
FCM, такое аппаратное исключение вообще бывает? что-то сомневаюсь %)

Автор: FCM 17.8.2009, 19:40
Формально приведено в одной книжке (Рихтер "Windows via С/С++") в главе про SEH

Автор: GoldFinch 17.8.2009, 21:27
вообщето оно генерится инструкцией into
как вы его генерили?

Автор: GremlinProg 18.8.2009, 08:13
FCM, представляешь, сколько бы проблем было при поднятии такого исключения на автомате?
флаг OF(overflow) очень часто используется штатно для определения критериев завершения циклов,
поэтому такое переполнение не генерируется по-умолчанию

если нужно, просто генерируй его сам:
Код

if( ( (ULONGLONG)x + y ) >> 32 ){
  ::RaiseException( EXCEPTION_INT_OVERFLOW, EXCEPTION_EXECUTE_HANDLER, 0, NULL );
}


into - тоже подойдет, но оно тестирует OF, конкретно по факту операции, типа такого:
Код

x += y;
__asm into;

Автор: GoldFinch 18.8.2009, 10:05
Цитата(GremlinProg @  18.8.2009,  09:13 Найти цитируемый пост)
x += y;
__asm into;

никакой гарантии, что OF не будет сброшен\установлен кодом между непосредственной операцией сложения и __asm

Добавлено через 3 минуты и 57 секунд
Цитата(GremlinProg @  18.8.2009,  09:13 Найти цитируемый пост)
флаг OF(overflow) очень часто используется штатно для определения критериев завершения циклов,

в любой операции сравнения на больше\меньше проверяется равенство флагов знаков и переполнения

Автор: GremlinProg 18.8.2009, 10:19
Цитата(GoldFinch @  18.8.2009,  12:05 Найти цитируемый пост)
никакой гарантии, что OF не будет сброшен\установлен кодом между непосредственной операцией сложения и __asm

при чем тут сброс?

add, inc, sub, dec, mul - все устанавливают OF в соответствии с результатом,
сброс тут не нужен,
если нужно что-то более сложное - встроенный ассемблер в помощь,
а без него - RaiseException, как я уже показал

Автор: GoldFinch 18.8.2009, 12:17
GremlinProg
RaiseException который ты показал сводит на нет весь смысл into, изза немеряного оверхеда, непонятно вообще зачем бросать EXCEPTION_INT_OVERFLOW если можно бросить чтоугодно, всеравно там if

как устанавливается и сбрасывается OF я знаю, любая арифметическая инструкция, в том числе cmp, между сложением и into поменяет OF, кроме того, порядок вызова операторов перед __asm никем не гарантируется, 
  a+=b; x+=y; __asm into
может скомпилироваться в аналог
  x+=y; a+=b; __asm into

Автор: GremlinProg 18.8.2009, 12:44
Цитата(GoldFinch @  18.8.2009,  14:17 Найти цитируемый пост)
RaiseException который ты показал сводит на нет весь смысл into

into тут ни при чем, смысл RaiseException как раз в поднятии исключения без использования асма, и соответственно into
RaiseException - равнозначная замена, только с учетом того, что тут можно бросить не обязательно EXCEPTION_INT_OVERFLOW, а любое другое, которое программа в состоянии обработать (вплоть до критического)
любой программист в состоянии завести свой список исключений и работать с ним в дополнение ко всем системным исключениям (mc.exe в помощь)
Цитата(GoldFinch @  18.8.2009,  14:17 Найти цитируемый пост)
всеравно там if

if тут опять же ни при чем, т.к. от OF и  into тут уже ни чего не будет зависеть
Цитата(GoldFinch @  18.8.2009,  14:17 Найти цитируемый пост)
 любая арифметическая инструкция, в том числе cmp, между сложением и into поменяет OF

не любая
Цитата(GoldFinch @  18.8.2009,  14:17 Найти цитируемый пост)
порядок вызова операторов перед __asm никем не гарантируется, 

чтобы порядок не имел значения, у программиста должен быть другой оч. полезный инструмент - голова


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

Автор: GoldFinch 18.8.2009, 13:00
GremlinProg
дополнительное вычисление(?) "result >> 32" +  if это в сотни раз медленнее однобайтовой into которая выполняется за 0 или 1 тактов,
это называется "оверхед"
без into это должно реализовываться как jo/jno - тот же if, и это замена одного подхода на другой, 
можно писать into, можно писать jo, это разная логика кода - исключение и условие

Цитата(GremlinProg @  18.8.2009,  13:44 Найти цитируемый пост)
не любая

какая?

Цитата(GremlinProg @  18.8.2009,  13:44 Найти цитируемый пост)
чтобы порядок не имел значения, у программиста должен быть другой оч. полезный инструмент - голова

это вообще к чему?

Автор: GremlinProg 18.8.2009, 13:41
Цитата(GoldFinch @  18.8.2009,  15:00 Найти цитируемый пост)
дополнительное вычисление(?) "result >> 32" +  if это в сотни раз медленнее однобайтовой into которая выполняется за 0 или 1 тактов

это к теме не относится, причем даже  "сотни раз" - это уже перебор

Цитата(GoldFinch @  18.8.2009,  15:00 Найти цитируемый пост)
без into это должно реализовываться как jo/jno - тот же if, и это замена одного подхода на другой, 

поздравляю, GoldFinch, ты освоил начальные навыки ассемблера, только к теме это так же не относится

Цитата(GoldFinch @  18.8.2009,  15:00 Найти цитируемый пост)
можно писать into, можно писать jo, это разная логика кода - исключение и условие

это было наглядно продемонстрировано моим первым постом
Цитата(GoldFinch @  18.8.2009,  15:00 Найти цитируемый пост)
какая?

очевидно все те арифметические операции, которые это переполнение не генерируют: DIV, IDIV, и т.п.

Цитата(GoldFinch @  18.8.2009,  15:00 Найти цитируемый пост)
это вообще к чему?

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

Автор: GoldFinch1 18.8.2009, 14:08
Признаю я был не прав. Как часто бывает, уверенность в своих знаниях меня подвела. 
Решив посмотреть как ведет себя div, я скомпилил в фасме код
Код

format PE

mov eax,1
mov ecx,2
div ecx
int3

запустил, и получил пресловутый Integer Overflow. Все таки не into единым.

Цитата(GremlinProg @  18.8.2009,  13:41 Найти цитируемый пост)
очевидно ... DIV, IDIV, и т.п.

Уважаемый GremlinProg, опомнись, и перестать писать то чего не знаешь. Ты вводишь в заблуждение участников форума, да и выглядит это не красиво.
Любой справочник говорит: 
DIV -- Unsigned Divide 
Flags Affected
OF, SF, ZF, AR, PF, CF are undefined. 


За сим отправляюсь отдыхать недельку, пока основной акк в бане.

Автор: GremlinProg 18.8.2009, 14:26
Цитата(GoldFinch1 @  18.8.2009,  16:08 Найти цитируемый пост)
Признаю я был не прав. Как часто бывает, уверенность в своих знаниях меня подвела. Решив посмотреть как ведет себя div, я скомпилил в фасме код
Код

format PE

mov eax,1
mov ecx,2
div ecx
int3

запустил, и получил пресловутый Integer Overflow. Все таки не into единым.
Цитата(GremlinProg @  18.8.2009,  15:41 Найти цитируемый пост)
очевидно  ... DIV, IDIV, и т.п.

Уважаемый GremlinProg, опомнись, и перестать писать то чего не знаешь. Ты вводишь в заблуждение участников форума, да и выглядит это не красиво.Любой справочник говорит: DIV -- Unsigned Divide Flags Affected OF, SF, ZF, AR, PF, CF are undefined. За сим отправляюсь отдыхать недельку, пока основной акк в бане.

я даже сохраню это на память )

уважаемый GoldFinch, честно говоря не знаю где ты мог получить в этом коде Integer Overflow, очевидно где-то ранее предоставленного кода, но опираясь даже на справку, которую ты так любезно нам предоставил:
Цитата(GoldFinch1 @  18.8.2009,  16:08 Найти цитируемый пост)
OF, SF, ZF, AR, PF, CF are undefined

are undefined означает не определено, т.е. не затрагиваются, они могут затрагиваться любыми предыдущими операциями, но не данной

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

Автор: FCM 18.8.2009, 16:59
Цитата(GoldFinch @  17.8.2009,  21:27 Найти цитируемый пост)
вообщето оно генерится инструкцией into
как вы его генерили?

Да никак не генерил - прочитал книгу, попробовал . И почему это называется аппаратным исключением, если я его сам должен генерить? Было бы разумным иметь опцию в свойствах проекта, включающую/отключающую генерацию этого исключения.

Кстати пробовал еще с помощью EXCEPTION_ARRAY_BOUNDS_EXCEEDED отловить выход за пределы С-массива -  то же безрезультатно (в Debug это ловилось RTL'ю, а в Release- никак)

A EXCEPTION_FLT_***  фиксируется (после того как контрольным словом отключить их FPU-обработу).
Хотя тут два момента непонятны. 
1) Если  аппаратное FLT-исключение нигде не обработано, Windows его определяет (выдает правильный 16-чный код исключения), но почему-то называет unknown software exception
2) Просматривал статусное слово различных FLT-операций и заметил, что в Release фиксируется меньше критических FLT-событий. Если Debug и Release отличается толко настройками RTL, то как настройки RTL влияют на FPU-обработку FLT-исключений.?

Если взять простое консольное приложение, то "казалось бы" после его одевания при компоновке в SEH-фреймы оно должно иметь внешний фрейм от windows, потом фреймы (или аналоги?) от RTL, потом пользовательские (если есть) ловушки, а аппаратные средства обработки еще глубже. И каким боком туда залезает RTL (в С++ еще минимально , в некоторых языках еще более выраженно).

Не совсем понятно, что собственно генерит аппаратные исключения - CPU/FPU или какие-нибудь драйвера. Также не понятно, как FPU обрабатывает EXCEPTION_FLT_*** действительно аппаратно или драйвера.  Функции VС++ напрямую работают c железом или через WinApi ? 
Например попытка открыть несуществующий файл - приводит к соответствующему errno. Кто его назначает? Это же программное исключение?


Автор: GremlinProg 19.8.2009, 10:55
Цитата(FCM @  18.8.2009,  18:59 Найти цитируемый пост)
И почему это называется аппаратным исключением, если я его сам должен генерить?

ну, потому что процессор не знает ни EXCEPTION_INT_OVERFLOW, ни любой другой статус, привычный нам, он просто генерирует аппаратное прерывание, которое перемещает исполнение кода на соответствующий адрес в векторе прерываний, а оттуда уже операционка нас информирует о случившемся через SEH (в документации такие прерывания обозначаются через решетку: #OF(overflow), #DE(divide error) и т.п.)
Цитата(FCM @  18.8.2009,  18:59 Найти цитируемый пост)
Было бы разумным иметь опцию в свойствах проекта, включающую/отключающую генерацию этого исключения.

в принципе, может и появится в будущем,
есть же опция /fp:except, которая расставляет WAIT'ы после любых обращений к FPU
тут в принципе аналогично - после целочисленных вычислений вставлять into, но по-моему, от этого будет только больше проблем, чем пользы
Цитата(FCM @  18.8.2009,  18:59 Найти цитируемый пост)
Кстати пробовал еще с помощью EXCEPTION_ARRAY_BOUNDS_EXCEEDED отловить выход за пределы С-массива -  то же безрезультатно (в Debug это ловилось RTL'ю, а в Release- никак)

ну так проверка на выход за границы массива только в дебаге и ведется, можешь и в релизе ее включить, только зачем оно надо, это ведь отладочный механизм
Цитата(FCM @  18.8.2009,  18:59 Найти цитируемый пост)
Не совсем понятно, что собственно генерит аппаратные исключения - CPU/FPU или какие-нибудь драйвера

сопроцессор и генерит
Цитата(FCM @  18.8.2009,  18:59 Найти цитируемый пост)
как FPU обрабатывает EXCEPTION_FLT_*** действительно аппаратно или драйвера

он не обрабатывает EXCEPTION_FLT_***
он обрабатывает свои контрольные регистры: если поднят флаг исключения (одного из 6), и если это исключение выключено по маске, то генерирует какое-то общее прерывание для исключений (смотри документацию, не помню какое именно)
если исключение маскируется, то FPU просто заменяет результат одним из табличных значений:
Код

Ошибка стека Неопределенность 
Операция с неподдерживаемым числом Неопределенность 
Операция с SNAN QNAN 
Сравнение числа с NAN C0 = C2 = C3 = 1 
Сложение бесконечностей с одним знаком или вычитание  — с разным Неопределенность 
Умножение нуля на бесконечность Неопределенность 
Деление бесконечности на бесконечность или 0/0 Неопределенность 
Команды FPREM и FPREM1, если делитель  — 0 или делимое — бесконечность Неопределенность и C2 = 0 
Тригонометрическая операция над бесконечностью Неопределенность и C2 = 0 
Корень или логарифм, если x < 0, log(x+1), если x < -1 Неопределенность 
FBSTP, если регистр-источник пуст, содержит NAN, бесконечность или превышает 18 десятичных знаков Десятичная неопределенность 
FXCH, если один из операндов пуст Неопределенность 

и продолжает работать дальше
Цитата(FCM @  18.8.2009,  18:59 Найти цитируемый пост)
Функции VС++ напрямую работают c железом или через WinApi ? Например попытка открыть несуществующий файл - приводит к соответствующему errno. Кто его назначает? Это же программное исключение?

с железом работают драйвера, а errno ставит CRT, и это уже не исключение, это что-то вроде упрощенного аналога для GetLastError

Автор: FCM 20.8.2009, 11:05
Спасибо за ответы.
Цитата(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 )

Автор: GremlinProg 20.8.2009, 12:35
Цитата(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-сторож

Автор: FCM 21.8.2009, 11:58
Я тут попробовал в одной программе, где просто просматривал статусное слово при 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) дело не доходит, но и мой обработчик тоже реально не выполняется - программа прекращает выполнение в месте возникновения исключения.
Я пробовал вложенные обработчики с фильтрами, настроенными непосредственно на вышеуказанные исключения - тоже не попадаю в тело обработчика и не получаю окошко от внешних (финальных) обработчиков (- программа прекращает выполнение в месте возникновения исключения.).


Автор: GremlinProg 21.8.2009, 12:37
Цитата(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, 14:28
для включения сразу нескольких исключений все аналолгично:
Код

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

Автор: FCM 21.8.2009, 17:38
Цитата(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?).
 

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

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

Автор: FCM 21.8.2009, 19:52
Как просмотреть регистр я не знаю.
Я вывожу текущее контрольное слово

до моих установок имею в двоичном формате
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

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

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

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

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

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

В отладчике тоже посмотрю.

Автор: FCM 22.8.2009, 09:38
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


Автор: GremlinProg 22.8.2009, 09:42
вот сейчас получил 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-сборку это не оказывает ни какого влияния (просто в дебаге удобно по-быстрому найти ошибку, не расставляя брейкпойнты)

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

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

Автор: FCM 23.8.2009, 08:47
Понятно, спасибо

А вот применение signal - это только для установки дополнительных "пунктов" для _XcptFilter?
Или что-то более универсальное?

Автор: GremlinProg 23.8.2009, 11:15
в 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

Автор: GremlinProg 23.8.2009, 12:06
вот тут, кстати описана одна особенность UnhandledExceptionFilter при работе под отладчиком: http://support.microsoft.com/kb/173652
+ дополнения по финальным исключениям

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

Автор: Earnest 24.8.2009, 07:20
Да, это кстати хороший (трудно-обнаружаемый) способ обнаружения отладчика... (это к вопросу о защите программ). Пардон за smile 

Автор: FCM 27.8.2009, 14:09
_CppXcptFilter вызывается в crtdll.c. В crt0.c вызывается только к _XcptFilter.
А какие из файлов crt0.c, crtexe.c, crtdll.c используются например для консольных приложений, dll-приложений? 
Есть ли какая-нибуль связь между _CppXcptFilter,  _CppUnhandledExceptionFilter (упомянутой в книге Рихтера "windows via C++"),  terminate()?



Автор: GremlinProg 28.8.2009, 09:41
Цитата(FCM @  27.8.2009,  16:09 Найти цитируемый пост)
Есть ли какая-нибуль связь между _CppXcptFilter,  _CppUnhandledExceptionFilter (упомянутой в книге Рихтера "windows via C++"),  terminate()?

я вообще-то не нашел ни где _CppUnhandledExceptionFilter, ни в документации, ни в образах и объектных файлах,
посмотри, правильно-ли написано название функции, либо дай конкретные координаты источника (страница, издание, рус/eng, либо конкретную главу/подглаву)

можно только предположить, что это простой фильтр, который вне отладчика перехватывает исключение 'msc'|0xE0000000, извлекает из него объект типа exception и показывает диалог с сообщением от этого исключения, либо в книге был дан просто пример как реализовать UnhandledExceptionFilter для C++ исключений

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

Автор: FCM 28.8.2009, 10:10
Цитата(GremlinProg @  28.8.2009,  09:41 Найти цитируемый пост)
я вообще-то не нашел ни где _CppUnhandledExceptionFilter, ни в документации, ни в образах и объектных файлах,
посмотри, правильно-ли написано название функции, либо дай конкретные координаты источника (страница, издание, рус/eng, либо конкретную главу/подглаву)


Немного неточно я указал название функции:
Джеффри Рихтер, Кристоф Назар
Windows via C/C++. Программирование на языке Visual C++. СПб 2008. 
В главе 25, стр 800 упоминается функция __CxxUnhandledExceptionFilter.

2) Там же далее (c.825) написано , что С++ исключения  в Visual С++ реализуются с помощью SEH.  Но непонятно, разве можно с помощью SEH сделать корреткную деструкцию объектов классов. Или он должен был написать, что С++ исключения  реализуются через SEH, только в асинхронной модели С++ исключений (/EHa)?
 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)