try catch в кроccплатформенных исходникахПостараюсь коротко. Думаю что всем программистам на Си с детства знакома подобная конструкция:
Назначение её в том чтобы не уронить программу в случае ошибки в коде. По крайней мере обычно так это происходит под Windows. Под Linux, или просто GCC компилятором, дела обстоят совсем иначе. GCC благополучно игнорирует любые ошибки внутри try и программа с грохотом падает. С сам catch реагирует только на программные исключения (которые я за жизнь применять только раз, и то заменял им множество переходов по метке). Конешно кто-то может сказать что это правильно и ближе к стандарту. А для программы, которая повредила свои данные, наилудший выход - совершить харакири. Приведу простой пример. Есть некая программа которая получает котировки по курсу валют, и есть в ней такая интересная фукнция, как проговаривание этих котировок в слух. Сама звуковая система устроена прямо скажем не просто (надо чтобы она произносила цифры, весила мало, и можно было вставлять другие языки. А попросту содержит в себе кодек, работающий с файлом похожим на базу). Предположим что в ней всё таки нашлась некая ошибка, которую сразу не заметили. Здесь и приходит на выручку знаменитый try. И смысл его не в том чтобы проигнорировать проблему, а в том чтобы насовсем заблокировать злощастную речевую систему, и сообщить об этом, в том случае если в ней были замечены какие-то проблемы. это позволит не уронить программу в отвественный момент. В принципе если программа написана совсем криво, то она может и порушить свои данные (хотя и целостность важных данных тоже контролировать не сложно). Ну а в целом подобный трюк работает хорошо и не спасает только в самых экзотических случаях. Так вот, повторю ещё раз. В GCC try не работает. Всё что можно сделать, это обработать сигнал и сделать что-то отдалённо похожее:
throw внутри сигнала, послать так же не получится. К тому же встаёт ещё одна проблема. В программе может быть очень много потоков, а обработчик сигналов у нас один на всех. В прочем как известно обычно и в Windows обработчик исключения один на всю программу (меняется только его реакция на ошибку). Спасает нас то обстоятельство, что поток вызвавший исключение (сигнал), очень легко определить. Функция pthread_self(); внутри обработчика сигнала, однозначно расскажет из какого потока пришёл этот сигнал. А для того чтобы не вставлять в обработчик всякие std::map и не следить за завершением каждого потока, значение sigjmp_buff можно прикрепить к самому потоку. Конечный исходникПростой пример. Данный исходник не позволяет делать вложенных try блоков:Исходник позволяющий делать вложенные try блоки: Последний исходник так же позволяет делать блоки с автоматической блокировкой. Например:
В данном случае если внутри _try_safe случится деление на ноль. То будет вызван _catch_safe блок. А кроме того весь кусок кода заблокируется автоматически, т.е. при повторном исполнении эти строки уже будут восприниматься как пустое место и выполняться не станут. Делается это с помощью статических переменных внутри блока. Часто столько простыми действиями ничего не обходится, но показать это стоило.
В теории можно было подменить даже обычный try. Потому что любой Си позволяет переопределять ключевые слова, подменяя их свойства. Можете сами попробовать:
ПоправкиВ BeOS: posix вариант работает только в свежих версиях Hauku. В более ранних билдах обработка сигналов работала неправильно. А в Pe, и Dano версиях вообще небыло обработки сигналов, а так же нормальных механизмов для их замены, не считая встроенной системы отладки (которая для этого мало подходит).[Proteus 29.10.2007] icq:133575351 lawnmower-man@mail.ru |