Conceitos básicos usando gerenciado exceções
Este tópico discute a manipulação de exceções em aplicativos gerenciados.Ou seja, um aplicativo que é compilado com o /clr opção de compilador.
Neste tópico
Lançar exceções em /CLR.
Blocos de Try/Catch para extensões do CLR
Comentários
Se você compilar com o /clr opção, você pode manipular exceções do CLR, bem como o padrão manipulação de exceção de C++ e tratamento de exceção estruturado (SEH).Uma exceção CLR é qualquer exceção lançada por um tipo gerenciado.O System::Exception classe fornece muitos métodos úteis para o processamento de exceções do CLR e é recomendado como uma classe base para classes de exceção definido pelo usuário.
Não há suporte para detectar tipos de exceções derivados de uma interface em /clr.Além disso, o common language runtime não permite capturar exceções de estouro de pilha; uma exceção de estouro de pilha encerrará o processo.
Para obter mais informações sobre as diferenças na manipulação de exceção em aplicativos gerenciados e não gerenciados, consulte diferenças na exceção manipulação comportamento em Managed Extensions for C++.
Lançar exceções em /CLR.
Expressão C++ throw é estendido para lançar um identificador para um tipo CLR.O exemplo a seguir cria um tipo de exceção personalizada e, em seguida, lança uma instância desse tipo:
// 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;
}
Um tipo de valor deve ser in a box antes de ser lançada:
// clr_exception_handling_2.cpp
// compile with: /clr /c
value struct MyValueStruct {
int i;
};
void GlobalFunction() {
MyValueStruct v = {11};
throw (MyValueStruct ^)v;
}
Blocos de Try/Catch para extensões do CLR
O mesmo tente/catch estrutura de bloco pode ser usada para capturar exceções nativas e 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 );
}
}
}
Saída
In 'catch(CMyClass& catchC)'
2
In 'catch(MyStruct^ catchException)'
11
Ordem de desenrolar para objetos do C++
Desenrolar ocorre para quaisquer objetos C++ com destruidores que possam estar na pilha de tempo de execução entre a função throwing e a função de tratamento.Como tipos CLR são alocados na pilha, desenrolar não se aplicar a eles.
A ordem de eventos para uma exceção lançada é a seguinte:
O runtime examina a pilha olhando para a cláusula catch apropriada ou no caso de SEH, um exceto filtro SEH para capturar a exceção.Catch cláusulas são pesquisados primeiro na ordem léxica e depois dinamicamente para baixo na pilha de chamadas.
Depois que o manipulador correto for encontrado, a pilha é organizada para esse ponto.Para cada chamada de função na pilha de objetos locais são destruídos e __finally blocos são executados da maioria aninhados para fora.
Depois que a pilha é organizada, a cláusula catch é executada.
Captura de tipos não gerenciados
Quando um tipo de objeto não gerenciado é lançado, é empacotada com uma exceção do tipo System::Runtime.InteropServices::SEHException.Ao procurar o apropriado catch cláusula, há duas possibilidades.
Se for encontrado um tipo de C++ nativo, a exceção é porem e comparado com o tipo encontrado.Essa comparação permite que um tipo de C++ nativo ser identificada de forma normal.
No entanto, se um catch cláusula do tipo SEHException ou qualquer de suas classes base é examinada primeiro, a cláusula irá interceptar a exceção.Portanto, você deve colocar todas as cláusulas catch catch tipos C++ nativos primeiro antes de qualquer catch cláusulas de tipos CLR.
Observe que
catch(Object^)
e
catch(...)
ambos irá capturar qualquer tipo lançado incluindo exceções SEH.
Se um tipo não gerenciado é detectado pelo catch(Object^), não destruirá o objeto lançado.
Ao lançar ou capturar não gerenciado exceções, recomendamos que você use o /EHsc opção de compilador em vez de /EHs ou /EHa.
Consulte também
Referência
safe_cast (Extensões de Componentes C++)
Tratamento de exceção no Visual C++