Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе рассматривается обработка исключений в управляемых приложениях. То есть приложение, скомпилированное с параметром компилятора /clr .
В этом разделе
Замечания
При компиляции с параметром /clr вы можете обрабатывать исключения CLR так же, как и стандартные исключения. Класс Exception предоставляет множество полезных методов для обработки исключений CLR и рекомендуется в качестве базового класса для пользовательских классов исключений.
Перехват типов исключений, производных от интерфейса, не поддерживается в /clr. Кроме того, общий язык выполнения (CLR) не позволяет перехватывать исключения переполнения стека; исключение переполнения стека завершит процесс.
Дополнительные сведения о различиях в обработке исключений в управляемых и неуправляемых приложениях см. в разделе Различия в поведении обработки исключений в управляемых расширениях для C++.
Создание исключений в /clr
Выражение throw в C++ расширено, чтобы выбрасывать дескриптор для типа CLR. В следующем примере создается настраиваемый тип исключения, а затем создается экземпляр этого типа:
// clr_exception_handling.cpp
// compile with: /clr /c
ref struct MyStruct: public System::Exception {
public:
int i;
};
void GlobalFunction() {
MyStruct^ pMyStruct = gcnew MyStruct;
throw pMyStruct;
}
Перед выполнением выброса значимый тип должен быть упакован.
// clr_exception_handling_2.cpp
// compile with: /clr /c
value struct MyValueStruct {
int i;
};
void GlobalFunction() {
MyValueStruct v = {11};
throw (MyValueStruct ^)v;
}
Блоки Try/Catch для расширений CLR
Одну и ту же try/catch структуру блоков можно использовать для перехвата как исключений CLR, так и собственных исключений.
// clr_exception_handling_3.cpp
// compile with: /clr
using namespace System;
ref struct MyStruct : public Exception {
public:
int i;
};
struct CMyClass {
public:
double d;
};
void GlobalFunction() {
MyStruct^ pMyStruct = gcnew MyStruct;
pMyStruct->i = 11;
throw pMyStruct;
}
void GlobalFunction2() {
CMyClass c = {2.0};
throw c;
}
int main() {
for ( int i = 1; i >= 0; --i ) {
try {
if ( i == 1 )
GlobalFunction2();
if ( i == 0 )
GlobalFunction();
}
catch ( CMyClass& catchC ) {
Console::WriteLine( "In 'catch(CMyClass& catchC)'" );
Console::WriteLine( catchC.d );
}
catch ( MyStruct^ catchException ) {
Console::WriteLine( "In 'catch(MyStruct^ catchException)'" );
Console::WriteLine( catchException->i );
}
}
}
Выходные данные
In 'catch(CMyClass& catchC)'
2
In 'catch(MyStruct^ catchException)'
11
Порядок очистки для объектов C++
Очистка происходит для любых объектов C++ с деструкторами, которые могут находиться в стеке времени выполнения между функцией создания и функцией обработки. Поскольку типы CLR выделяются в куче, очистка к ним не применяется.
Порядок событий для выбрасываемого исключения следующий:
Среда выполнения выполняет проход по стеку в поисках соответствующего блока catch или, в случае SEH, фильтра обработки исключений для SEH, чтобы перехватить исключение. Сперва блоки catch проверяются в лексическом порядке, а затем динамически по стеку вызовов.
После обнаружения правильного обработчика стек разматывается до этой точки. Для каждого вызова функции в стеке локальные объекты уничтожаются и блоки __finally исполняются, начиная с самого вложенного.
После развёртывания стека выполняется блок catch.
Перехват неуправляемых типов
При возникновении неуправляемого типа объекта он упаковывается за исключением типа SEHException. При поиске соответствующего catch предложения существует два варианта.
Если обнаружен собственный тип C++, исключение раскроется и сравнивается с обнаруженным типом. Это сравнение позволяет перехватить встроенный тип C++ стандартным способом.
Однако если блок
catchтипа SEHException или любой из его базовых классов рассматривается сначала, блок будет перехватывать исключение. Поэтому следует поместить все предложения catch, которые перехватывают нативные типы C++, перед тем как любые предложения catch типов CLR.
Обратите внимание, что
catch(Object^)
и
catch(...)
будет перехватывать любой брошенный тип, включая исключения, обрабатываемые с помощью SEH.
Если неуправляемый тип перехватывается catch(Object^), это не приведет к уничтожению выброшенного объекта.
При вызове или перехвате неуправляемых исключений рекомендуется использовать параметр компилятора /EHsc вместо /EHs или /EHa.