Exceções: liberando 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:
Tratando a exceção localmente
Lançando exceções destruído depois de objetos
As exceções lançadas pela estrutura ou pelo seu aplicativo interrompem o fluxo de programa normal. Assim, é muito importante manter a próximo controle de objetos de forma que você pode descartar corretamente no caso de uma exceção é gerada.
Há dois métodos principais para fazer isso.
As exceções de identificador que usam localmente as palavras-chave de try e de catch , destroem todos os objetos com uma instrução.
Destruir qualquer objeto no bloco de catch antes de gerar a exceção fora do bloco para manipulação adicional.
Essas duas abordagens são ilustradas em como soluções ao 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 gravado acima, myPerson não será excluído se uma exceção é gerada por SomeFunc. A execução pular diretamente ao manipulador externo seguinte de exceção, ignorando a saída da função normal e o código que exclui o objeto. O ponteiro para o objeto sai do escopo quando a exceção sai da função, e a memória ocupada pelo objeto será recuperada nunca como o programa está em execução. Este é um vazamento de memória; o será detectado usando o diagnóstico de memória.
Tratando a exceção localmente
O paradigma de try/catch fornece um método de programação defensivo para evitar possíveis vazamentos de memória e assegurar que os objetos a serem destruídos quando as exceções ocorrem. Por exemplo, o exemplo mostrado anteriormente neste artigo pode ser reescrito como segue:
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;
}
Esse novo exemplo configura um manipulador de exceção para capturar a exceção e para tratá-la localmente. A função é encerrado normalmente e destrói o objeto. O aspecto importante deste exemplo é que um contexto para capturar a exceção é estabelecido com os blocos de try/catch . Sem um quadro local de exceção, a função nunca saberia se uma exceção tiver sido lançada e não teria a possibilidade é encerrado normalmente e destruir o objeto.
Lançando exceções destruído depois de objetos
Outra maneira de tratar exceções é transmiti-los sobre o contexto externo seguinte manipulação de exceções gerais. No bloco de catch , você pode fazer alguma limpeza de seus objetos atribuídos localmente e depois lançar exceção em para processamento posterior.
A função de reprodução pode ou não precise desaloque objetos do heap. Se a função sempre desaloca o objeto do heap antes de retornar os casos normais, a função também deverá desalocar o objeto do heap antes de gerar a exceção. Por outro lado, se a função desaloca normalmente o objeto antes de retornar os casos normais, você deve decidir EM UMA base casuística se o objeto do heap deve ser desalocada.
O exemplo a seguir mostra como os objetos localmente atribuídos 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 do quadro; o destruidor do objeto do quadro também é chamado.
Se você chamar funções que podem lançar exceções, você pode usar blocos de try/catch para garantir que o capturar exceções e tem uma possibilidade destruir todos os objetos que você criar. Em particular, lembre-se de que muitas funções MFC podem lançar exceções.
Para obter mais informações, consulte Exceções: Capturando e excluindo exceções.