2010-09-24 2 views

ответ

19

Вы на самом деле есть три механизма:

  • C++ исключения, реализованные компилятором (try/catch)
  • Структурированная обработка исключений (SEH), предоставляемой ОС Windows (__try/__except)
  • MFC макросы исключения (TRY, CATCH - на основе исключений SEH/C++ - см. также комментарий TheUndeadFish)

Исключения C++ обычно гарантируют автоматическую очистку во время разматывания стека (т. деструкторы локальных объектов), другие механизмы этого не делают.

Исключения C++ происходят только при их явной броске. Структурированные исключения могут возникать для многих операций, например. из-за неопределенного поведения, передачи недействительных указателей на API, размонтирование хранилища резервных копий файла с отображением памяти и многое другое.

MFC представила макросы исключения для поддержки исключений, даже если компиляторы их не реализовали.

+0

Только ради любопытства, MFC когда-либо предназначались для работы с любым компилятором, отличным от VC++? –

+2

Исключения для C++ не требуются для обеспечения очистки. Скомпилировать с/EHa. –

+0

MFC действительно работал на Watcom C/C++ 10. Как-то. Без волшебников и прочее. – peterchen

6

Исключение C++ - это особенность языка программирования C++. Структурированное исключение - это другая концепция операционной системы Windows. Эти два используют аналогичный синтаксис, но технически разные. Структурированные исключения Windows не только используются с C++, но также, например, с C.

Иногда решение для унификации обработки обоих: В приложении Windows вы можете предоставить функцию обработчика, которая улавливает все структурированные исключения и выдает исключение C++ (определенное вами).

4

Оба механизма обеспечивают раскручивание стека при возникновении ошибок.

Структурированные исключения предоставляются Windows, с поддержкой ядра. Они создаются Windows, если вы делаете что-то вроде доступа к недопустимому местоположению памяти. Они также используются для поддержки таких функций, как автоматический рост стека. Они используются довольно редко сами по себе, но языковые исключения на языках C++, .NET и подобных языках часто строятся поверх них. Вы используете специальные ключевые слова, такие как __try и __catch, чтобы справиться с этими исключениями. Однако иметь дело с ними сравнительно сложно и подвержено ошибкам, потому что вы можете разбить такие функции, как автоматическое расширение стека, а также потенциально исключить исключения языка C++.

Исключения C++ указаны языком C++. Типы данных, которые выбрасываются и захватываются, являются объектами C++ (включая возможность примитивных типов). Компилятор и среда выполнения реализуют их поверх основного структурированного механизма исключения. Это то, что вы получаете, если используете ключевые слова языка C++ try, catch и throw.

В исключениях SEH есть больше возможностей, чем исключения C++, такие как поддержка возобновления и так называемые «векторизованные» обработчики (которые получают уведомления об исключениях, но не обязательно предотвращают разворот стека), но если вы специально не знаете, что хотите используйте их, я бы избегал их. Вероятно, наиболее распространенным из них является запись дампа сбоя с использованием MiniDumpWriteDump, если ваша программа делает что-то незаконное или неопределенное.

1

Исключения C++ будут работать на кросс-платформе. К сожалению, SEH сильно ограничивает переносимость (за исключением случаев, когда они могут быть в разных версиях Windows).

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

7

Это тяжелая деталь реализации, но на Windows, С ++ исключение также исключение SEH. Код исключения - 0xE04D5343 (последние три байта = «MSC»). И вся регулярная поддержка SEH используется для размотки стека, получения автоматического кода очистки для запуска и фильтрации исключения, поэтому выбрано правильное предложение catch. Получение объекта исключенного исключения в выражении фильтра - это сантехника, которая добавляется в CRT, кроме того, что предоставляет SEH. SEH также поддерживает предложение __finally, но не используется в стандартном C++.

Еще одна деталь реализации - это настройка компилятора/EH. Значение по умолчанию (/ EHsc) позволяет компилятору оптимизировать созданный код и подавлять фильтры исключений, необходимые для автоматической очистки. Если он видит, что ни один из испущенных C++-кода не может вызвать исключение. Это прежде всего оптимизация пространства, небольшая оптимизация времени для кода x86, но не для кода x64. Чтобы получить автоматическую очистку для исключений SEH, вы должны скомпилировать с/EHa, чтобы эта оптимизация была подавлена.

Хорошей стратегией вступления в брак с исключениями C++ с помощью SEH является использование _set_se_translator(), поэтому вы можете перевести исключение SEH в исключение C++. Несмотря на то, что нередко разумно перехватывать исключения SEH, они почти всегда неприятны.

+0

Будет ли __try/__ исключением блокировать все исключения SEH, а также все исключения C++? – Alexandru

+0

Также важно отметить, что _set_se_translator() вызывается только один раз для каждого вызова функции в стеке, который имеет блоки try, в соответствии с MSDN, и должен быть установлен для каждой строки. – Alexandru

Смежные вопросы