Partilhar via


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 );
      }
   }
}

df24ysb6.collapse_all(pt-br,VS.110).gifSaída

In 'catch(CMyClass& catchC)'
2
In 'catch(MyStruct^ catchException)'
11

df24ysb6.collapse_all(pt-br,VS.110).gifOrdem 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:

  1. 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.

  2. 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.

  3. Depois que a pilha é organizada, a cláusula catch é executada.

df24ysb6.collapse_all(pt-br,VS.110).gifCaptura 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++

Outros recursos

Tratamento de Exceção (Extensões de Componentes C++)