Здравствуйте, MT, Вы писали:
MT>Можно ли перехватить фатальные ошибки вроде "Memory could not be read"?
[] MT>Но очевидно что не все ошибки перехватываются...
У Микрософта есть такая странная функция под названием _set_se_translator (см. в MSDN), которая позволяет преобразовывать структурное исключение Windows (см. SEH) в исключение C++.
Здравствуйте, <Аноним>, Вы писали:
А>Здравствуйте, MT, Вы писали:
MT>>Можно ли перехватить фатальные ошибки вроде "Memory could not be read"? А>[] MT>>Но очевидно что не все ошибки перехватываются...
А>У Микрософта есть такая странная функция под названием _set_se_translator (см. в MSDN), которая позволяет преобразовывать структурное исключение Windows (см. SEH) в исключение C++.
мы пользуемся SetUnhandledExceptionFilter — он практически все перехватывает, но у нас своя обработка ошибок, а так много статей есть и, в том числе в MSDN, о внутренностях SEH и как его подружить с CPP.
Здравствуйте, MT, Вы писали:
MT>Можно ли перехватить фатальные ошибки вроде "Memory could not be read"? MT>Пробовал так:
MT>
MT> try {
MT> } catch (...) {
MT> }
MT>
MT>Но очевидно что не все ошибки перехватываются...
Рассказываю (и показываю). То что вы называете фатальными ошибками на самом деле являются SEH-исключениями операционной системы (внимательно читаем Рихтера). Они возбуждаются в различных ситуациях, как то: доступ по неправильному адресу, переполнение стека, деление на нуль, ошибка сопроцессора и.т.д. Будучи неперехваченным, SEH-исключение вызывает появление хорошо известного окна с предложением впаять разработчику и принудительной остановки процесса. Как перехватывать такие исключения в C++. Метод __try __except обсуждать не буду, поскольку его использование в C++ программах -- это дурной тон и возможный конфликт с родными C++ исключениями. Наиболее простой подход -- использовать catch(...). Для того, чтобы это работало, необходимо правильно настоить компилятор. Насчет VC++ 6.0 не помню, а вот в 7.0/7.1 придётся повыделываться. Заходим на вкладочку свойств проекта C/C++ Code Generation. Там есть строчка Enable C++ exception. Смело ставим в этой строчке No. Дальше двигаемся в конец к секции Command Line. На соотвествующей вкладочке есть окошко, Additional Options. Вот здесь надо прописать /EHac. Почему так, спросите у Билла Гейтса. Чтобы жизнь была интересней и разнообразней, наверное. Не всё ж галочки в property tab мышкой переключать. В чем недостаток этого подхода -- невозможно определить тип исключения, и ,что более серьёзно, возникают проблемы с плавающей арифметикой. Имеется более усовершенствованный метод. Заключается он в использовании так называемого se транслятора. Вот примерный код.
Смысл в следующем. Вызовом функции _set_se_translator можно инсталировать функцию, которая будет получать управление в случае возникновения в текущем потоке SEH-исключения. Главное назначение этой функции -- получить код SEH-исключения, завернуть в подходящую обёртку и выбросить нормальное C++ исключение. Которое в дальнейшем можно поймать обычным catch. Коды этих исключений можно получить из windows.h, а описание -- в MSDN в статье про EXCEPTION_RECORD. Среди этих кодов есть семейство особо важных, связанных с плавающей точкой. При получении одного из этих кодов, надо делать маленькую дополнительную обработку. А именно, нужно командой fninit сбросить сопроцессор в нормальное состояние. Ну и загрузить подходящее слово управление. Иначе флаги исключений по-прежнему будут висеть в сопроцессоре, что вызовет возбуждение нового исключения при попытке его снова заюзать. Вообще, использование исключений сопроцессора -- это отдельный нетривиальный вопрос. Поскольку с ним связан целый рад фокусов, на которые можно напороться.
Здравствуйте, Шахтер, Вы писали:
Ш>Вообще, использование исключений сопроцессора -- это отдельный нетривиальный вопрос. Поскольку с ним связан целый рад фокусов, на которые можно напороться.
А интересно где нибудь можно по подробней про это почитать?