вот есть небольшой исходник. желающих прошу попытаться определить, какое значение вернёт main, а также расставить цифры в прокомметированных местах, отмечая порядок их выполнения. пожалуйста, указывайте компилятор и (при необходимости) другие релевантные детали, из-за которых, по вашему мнению, код будет выполняться именно в указанном порядке. бонусный вопрос: а какой порядок выполнения можно считать корректным? Код (Text): #include <windows.h> #include <intrin.h> #define int3() __debugbreak() volatile int a, b; int filter() { if (b < 0x10) { b += 0x10; // return EXCEPTION_CONTINUE_SEARCH; } if (b < 0x20) { b += 0x20; // return EXCEPTION_EXECUTE_HANDLER; } b -= 0x10; // return EXCEPTION_EXECUTE_HANDLER; } int main() { a = 0; // 01 b = 0; __try { a += 1; // 02 __try { a += 2; // 03 __try { a += 4; // 04 __try { a += 8; // int3(); } __finally { a -= 8; // int3(); } b += 4; // } __except(filter()) { a -= 4; // } b += 2; // } __finally { a -= 2; // } b += 1; // } __except(filter()) { a -= 1; // } return a + b; // } то же с подсветкой
catwalk_mission __try/__except/__finally это галимые микрософтные экстеншены, не имеющие никакого отношения к Стандарту. Так что все бонусные вопросы можно спустить в унитаз.
=P я не прошу это компилировать, кстати. просто приглашаю желающих подумать расставить с десяток чисел. компилятор попросил указывать только на случай варианта решения, несовпадающего с официальным мнением (т.е. с моим), но являющегося верным для какой-нибудь экзотической версии icc =) хотя... если ли смысл просить указывать компилятор в этом случае?.. в общем, как хотите =) но если что, будем разбираться, uguu~
catwalk_mission в последнем _finally блоке a = 5, b = 32, считал в уме мог ошибица. Ответ стало быть 37. Кстати _DEN_ не совсем прав, экстеншены как он их назвал совсем не микрософные, а компиляторные (т.е. реализация поверх механизмов ОС (seh то бишь) зависит от данного конкретного компилятора.
Цифирки забыл написать: Код (Text): Код: #include <windows.h> #include <intrin.h> #define int3() __debugbreak() volatile int a, b; int filter() { if (b < 0x10) { b += 0x10; // 06 return EXCEPTION_CONTINUE_SEARCH; } if (b < 0x20) { b += 0x20; // 07 return EXCEPTION_EXECUTE_HANDLER; } b -= 0x10; // 09 return EXCEPTION_EXECUTE_HANDLER; } int main() { a = 0; // 01 b = 0; __try { a += 1; // 02 __try { a += 2; // 03 __try { a += 4; // 04 __try { a += 8; // 05 int3(); } __finally { a -= 8; // int3(); } b += 4; // } __except(filter()) { a -= 4; // } b += 2; // } __finally { a -= 2; // 10 } b += 1; // } __except(filter()) { a -= 1; // } return a + b; // 11 }
TSS Ну так студию вроде не 1C писали)) Ну пусть будут микрософтно-интелловские, делов-то. Основной смысл в том, что эта тема должна быть в WIN32, а никак не в LANG.C.
ура-ура! первое решение есть. в настоящий момент собирается специальная комиссия, которая вынесет вердикт относительно представленного TSS варианта. возможно, в это время участники форума продемонстрируют другие решения? _DEN_ wasm.win32? или wasm.x64? механизмы операционных систем, на которых базируется __try\__except (и try\catch), конечно, играют важнейшую роль, но в этой теме я бы хотел сделать упор на механизм __try\__except\__finally, обеспечиваемый именно компиляторами C\C++ (и прилагаемыми к ним библиотекам времени выполнения). если модераторы посчитают, что это всё же неподходящий раздел, то они перенесут тему... наверное =) кстати, _DEN_, не хотите попробовать? расставить циферки?
catwalk_mission try/throw/catch не имеет никакого отношения к механизмам операционной системы. Нет, не хочу. Я не знаток всяких там vendor-specified расширений и быть таковым не собираюсь. Встречный вопрос: не желаете придумать 5 аргументов "за" и 5 аргументов "против" того чтобы перегружать оператор "точка" в C++?
Проверил на MSVC2008 свое решение, оно неверное. Насколько я помню, по теории связанную цепочку seh винда пробегает дважды, во второй раз выполняя так называемый unwinding, и в этот момент должны вызываться finally обработчики, но они похоже вызываются дважы(почему компилятор так решил я незнаю). Вобщем согласен с _DEN_, задачка на знание механизмов ОС, равно как и задачка на знание чисто С++ исключений была бы более интересной, чем разбираться, почему один компилятор делает так, а другой по другому.
Ursus try/catch - присущ языку. вот именно. что в Win. под другими осями - может быть другая реализация.
ну что, за сутки всего одно решение? давайте поактивнее! первому приславшему правильный вариант будет выслана банка ништяков! =) _DEN_ >Я не знаток всяких там vendor-specified расширений и быть таковым не собираюсь. ну как хотите. а ваш вопрос, к сожалению, к текущей теме не имеет никакого отношения – так что, пожалуй, как-нибудь в другой раз =P TSS да, неверное. ни с точки зрения теоретического стержня, который изначально закладывался в механизм __try\__except, ни с точки зрения его практической реализации в существующих системамах. сожалею. впрочем, по последнему вашему сообщению видно, что вы вплотную подошли к истине =)
catwalk_mission С теорией касательно механизмов исключений(как высокоуровневых, так и на уровне ядра) у меня все в порядке, уверяю вас. И да, к сожалению, это ваш вопрос к текущей теме не имеет никакого отношения.
catwalk_mission Вот именно поэтому и возникают такие проблемы, что одна софтина тихо завершается, другая какието мессаги с ошибками боксит, третья всю систему за собой валакёт.. Не говоря уже про быстродействие и надёжность. Обработка исключения через полядра пройдёт, есчо и в юзермоде, стоит немного исказить стек как рухнет всё приложение. Структурная обработка ислючений разумеется весьма полезный механизм, но использовать его стоит только в критически важных местах, где например иного способа проверить валидность указателя нет и есть вероятность краха. Обычно оборачивается процедура один-два раза в сех-фреймы. И рантайм предоставляемый средой всеголишь обёртка вокруг тяжелого механизма исключений. Следует сделать упор на проверку валидности(на ноль не делить, указатели проверять и пр). Например принимает процедура указатель внутрь таблицы, следует проверить вхождение указателя в диапазон, а не расчитывать на то, что среда решит эту проблему сама.
по всей видимости задачка пооказалась большинству слишком простой и неинтересной. а ведь на самом деле всё не так просто, как можно подумать с первого взляда. итак, ответ, который можно считать правильным с точки зрения логики try\except\finally: Код (Text): #include <windows.h> #include <intrin.h> #define int3() __debugbreak() volatile int a, b; int filter() { if (b < 0x10) { b += 0x10; // 06: выполняем фильтр первый раз... возвращаем "продолжить поиск"... return EXCEPTION_CONTINUE_SEARCH; } if (b < 0x20) { b += 0x20; // 07: выполняем фильтр второй раз... возвращаем "выполнить код в хендлере" // но перед тем, как выполнится код в хендлере, должна быть проведена раскрутка. // а поскольку раскрутка так и не будет доведена до конца, код в хендлере не выполнится... return EXCEPTION_EXECUTE_HANDLER; } b -= 0x10; // 09: выполняем фильтр в третий раз... возвращаем "выполнить код в хендлере" // (внимание: теперь мы готовимся выполнить код в другом хендлере) return EXCEPTION_EXECUTE_HANDLER; } int main() { a = 0; // 01 b = 0; __try { a += 1; // 02 __try { a += 2; // 03 __try { a += 4; // 04 __try { a += 8; // 05 int3(); // исключение! } __finally { a -= 8; // 08 выполняем раскрутку... int3(); // исключение во время локальной раскрутки! } b += 4; // -- этот код никогда не будет выполнен } __except(filter()) { a -= 4; // 10 успешно выполняем код в хендлере и... } b += 2; // 11 ...и продолжаем нормальное выполнение, как будто не было никаких исключений } __finally { a -= 2; // 12 выполняем finally (_не_ в рамках раскрутки) } b += 1; // 13 нормальное выполнение продолжается } __except(filter()) { a -= 1; // -- этот код никогда не будет выполнен } return a + b; // 14 a == 1, b == 0x23. return 0x24 == 36. } вероятно, большинство тех, кто размышлял над задачкой, представляли себе ход выполнения именно таким образом. однако, скомпилировав код с использованием стандартной CRT, они получили другой результат. а именно: 0x22 == 34. как верно было замечено TSS, один из блоков finally будет выполнен дважды. а именно – блок под номером 12: a -= 2. так что "альтернативно правильным" ответом можно считать 0x22 == 34. и, соответсвенно, вот циферки: Код (Text): #include <windows.h> #include <intrin.h> #define int3() __debugbreak() volatile int a, b; int filter() { if (b < 0x10) { b += 0x10; // 06: выполняем фильтр первый раз... возвращаем "продолжить поиск"... return EXCEPTION_CONTINUE_SEARCH; } if (b < 0x20) { b += 0x20; // 07: выполняем фильтр второй раз... возвращаем "выполнить код в хендлере" // но перед тем, как выполнится код в хендлере, должна быть проведена раскрутка. // а поскольку раскрутка так и не будет доведена до конца, код в хендлере не выполнится... return EXCEPTION_EXECUTE_HANDLER; } b -= 0x10; // 09: выполняем фильтр в третий раз... возвращаем "выполнить код в хендлере" // (внимание: теперь мы готовимся выполнить код в другом хендлере) return EXCEPTION_EXECUTE_HANDLER; } int main() { a = 0; // 01 b = 0; __try { a += 1; // 02 __try { a += 2; // 03 __try { a += 4; // 04 __try { a += 8; // 05 int3(); // исключение! } __finally { a -= 8; // 08 выполняем раскрутку... int3(); // исключение во время локальной раскрутки! } b += 4; // -- этот код никогда не будет выполнен } __except(filter()) { a -= 4; // 11 успешно выполняем код в хендлере и... } b += 2; // 12 ...и продолжаем нормальное выполнение, как будто не было никаких исключений } __finally { a -= 2; // !! 10 (раскрутка? wtf?!) // !! 13 выполняем finally (_не_ в рамках раскрутки) } b += 1; // 14 нормальное выполнение продолжается } __except(filter()) { a -= 1; // -- этот код никогда не будет выполнен } return a + b; // 14 a == 0xFFFFFFFF, b == 0x23. return 0x22 == 34. } причиной подобного поведения является ошибка в CRT. ошибка, должно быть, появилась весьма давно – неверный код присутвует даже в ntdll.dll от xp sp2. (кстати, в х64 всё в порядке, посколько аналогичный CRT-код попросту отсутствует за ненадобностью). да, функции с ошибкой – это '_unwind_handler4' и '_unwind_handler2'. надеюсь, кому-нибудь было интересно. будьте бдительны при обработке исключений! =)