Partilhar via


Exceções: Libertar objetos em exceções

Este artigo explica a necessidade e o método de liberar objetos quando ocorre uma exceção. Os tópicos incluem:

Exceções lançadas pela estrutura ou pelo seu aplicativo interrompem o fluxo normal do programa. Assim, é muito importante monitorar de perto os objetos para poder descartá-los corretamente no caso de ocorrer uma exceção.

Existem dois métodos principais para fazer isso.

  • Manipule exceções localmente usando as try palavras-chave e catch e destrua todos os objetos com uma instrução.

  • Destrua qualquer objeto no bloco catch antes de lançar a exceção fora do bloco para posterior tratamento.

Estas duas abordagens são ilustradas a seguir como soluções para o seguinte exemplo problemático:

void SomeFunc()        // Problematic code
{
   CPerson* myPerson = new CPerson;

   // Do something that might throw an exception.
   myPerson->SomeFunc();

   // Now destroy the object before exiting.
   // If SomeFunc above throws an exception this code will
   // not be reached and myPerson will not be deleted.
   delete myPerson;
}

Como escrito acima, myPerson não será excluído se uma exceção for lançada pela SomeFunc. A execução salta diretamente para o próximo manipulador de exceção externo, ignorando a saída normal da função e o código que exclui o objeto. O ponteiro para o objeto sai do escopo quando a exceção deixa a função, e a memória ocupada pelo objeto nunca será recuperada enquanto o programa estiver em execução. Esta é uma fuga de memória; ele seria detetado usando o diagnóstico de memória.

Manipulando a excepção localmente

O paradigma try/catch fornece um método de programação defensivo para evitar vazamentos de memória e garantir que seus objetos sejam destruídos quando ocorrerem exceções. Por exemplo, o exemplo mostrado anteriormente neste artigo pode ser reescrito da seguinte forma:

void SomeFunc()
{
   CPerson* myPerson = new CPerson;

   try
   {
      // Do something that might throw an exception.
      myPerson->SomeFunc();
   }
   catch (CException* e)
   {
      // Handle the exception locally
      e->Delete();
   }

   // Now destroy the object before exiting.
   delete myPerson;
}

Este novo exemplo configura um manipulador de exceção para capturar a exceção e manipulá-la localmente. Em seguida, ele sai da função normalmente e destrói o objeto. O aspeto importante deste exemplo é que um contexto para capturar a exceção é estabelecido com os blocos try/catch . Sem um quadro de exceção local, a função nunca saberia que uma exceção havia sido lançada e não teria a chance de sair normalmente e destruir o objeto.

Lançando exceções após destruir objetos

Outra maneira de lidar com exceções é passá-las para o próximo contexto externo de tratamento de exceções. No seu catch bloco, pode fazer alguma limpeza nos objetos que alocou localmente e, em seguida, lançar a exceção para que seja processada posteriormente.

A função de lançamento pode ou não precisar desalocar objetos do heap. Se a função sempre desaloca o objeto heap antes de retornar no caso normal, então a função também deve desalocar o objeto heap antes de lançar a exceção. Por outro lado, se a função normalmente não desaloca o objeto antes de retornar no caso normal, então você deve decidir caso a caso se o objeto heap deve ser deslocalizado.

O exemplo a seguir mostra como os objetos alocados localmente podem ser limpos:

void SomeFunc()
{
   CPerson* myPerson = new CPerson;

   try
   {
      // Do something that might throw an exception.
      myPerson->SomeFunc();
   }
   catch (CException* e)
   {
      e->ReportError();
      // Destroy the object before passing exception on.
      delete myPerson;
      // Throw the exception to the next handler.
      throw;
   }

   // On normal exits, destroy the object.
   delete myPerson;
}

O mecanismo de exceção desaloca automaticamente objetos de frame; o destrutor do objeto de frame também é chamado.

Se você chamar funções que podem lançar exceções, você pode usar blocos try/catch para garantir que você pegue as exceções e tenha a chance de destruir quaisquer objetos que você criou. Em particular, esteja ciente de que muitas funções MFC podem lançar exceções.

Para obter mais informações, consulte Exceções: capturando e excluindo exceções.

Ver também

Tratamento de exceções