Compartilhar via


Conceitos básicos em usando gerenciado exceções

Este tópico discute a manipulação de exceção nos aplicativos gerenciados. Isto é, um aplicativo que foi criado com a opção do compilador de /clr .

Neste tópico

  • Lançando exceções em /clr

  • Blocos try/catch para extensões de CLR

Comentários

Se você compila com a opção de /clr , você pode tratar exceções de CLR bem como Manipulação de exceção C++ padrão e manipulação de exceção estruturado (ELA). Uma exceção de CLR é qualquer exceção gerada por um tipo gerenciado. A classe de System::Exception fornece vários métodos úteis para processar exceções de CLR e é recomendada por uma classe base para classes definidos pelo usuário da exceção.

Capturar os tipos de exceção derivados de uma interface não tem suporte em /clr. Além disso, Common Language Runtime não permite capturar exceções de estouro de pilhas; 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 no comportamento de manipulação de exceção em extensões gerenciadas para C++.

Lançando exceções em /clr

A expressão do lançamento do C++ é estendida para gerar um identificador para um tipo CLR. O exemplo a seguir cria um tipo de exceção personalizada e lançará em 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 encaixotado antes de ser gerado:

// clr_exception_handling_2.cpp
// compile with: /clr /c
value struct MyValueStruct {
   int i;
};

void GlobalFunction() {
   MyValueStruct v = {11};
   throw (MyValueStruct ^)v;
}

Blocos try/catch para extensões de CLR

A mesma estrutura try/bloco decatch pode ser usado para capturar exceções e CLR nativos:

// 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 desenrolamento para objetos C++

Desenrolar ocorre para todos os objetos C++ com destruidores que podem estar na pilha de tempo de execução entre a função de reprodução e a função de tratamento. Como os tipos CLR são atribuídos no heap, desenrolando não se aplicam a eles.

A ordem de eventos para uma exceção gerada é a seguinte:

  1. O tempo de execução mostra a pilha que procura a cláusula adequada de captura ou, no caso de ELA, exceto o filtro para ELA, para capturar a exceção. As cláusulas de captura são pesquisadas primeiro na ordem léxica, e depois dinamicamente abaixo da pilha de chamadas.

  2. Uma vez que o manipulador correto está localizado, a pilha é distribuída depois a aquele ponto. Para cada chamada de função na pilha, seus objetos locais destructed os blocos e são executados __finally, da mais aninhado out.

  3. A pilha é distribuída depois uma vez, a cláusula de captura é executada.

Capturando tipos não gerenciado

Quando um tipo de objeto não gerenciado é gerado, está envolvido com uma exceção do tipo System::Runtime.InteropServices::SEHException. Ao procurar pela cláusula adequada de catch , há duas possibilidades.

  • Se um tipo de C++ nativo está localizado, a exceção será desempacotada e comparada ao tipo localizado. Essa comparação permite que um tipo de C++ nativo é capturado de maneira normal.

  • Porém, se uma cláusula de catch do tipo SEHException ou qualquer uma de suas classes base é verificada primeiro, a cláusula interceptará a exceção. Em virtude disso, você deve colocar as cláusulas de captura que capturam tipos de C++ nativo antes das cláusulas de captura de tipos CLR.

Observe que

catch(Object^)

e

catch(...)

ambos capturarão qualquer tipo gerado incluir ELA exceções.

Se um tipo gerenciado não é capturado pela captura Object^ (), não destruirá o objeto lançado.

Ao gerar ou ao capturar exceções não gerenciado, recomendamos que você use a opção do compilador de /EHsc em vez de /EHs ou de /EHa.

Consulte também

Referência

safe_cast (Extensões de Componentes C++)

Tratamento de exceções no Visual C++

Outros recursos

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