Tratamento de exceções: Parte II

Ordem dos Tratadores da Exceção Disparada

  • São testados na ordem em que são escritos.
  • A captura é realizada pelo 1º viável/compatível.
  • Apenas 1 tratador é usado.

Tratadores de exceções fora da ordem “mais especifico para o mais genérico” são ignorados.

Gerencia de recursos

Você deve tomar cuidado com exceções quando a Alocação de recursos e você precisa libera-los, exemplos:

  • Abrir um arquivo
  • Alocar memoria
  • Ajustar chave de controle de acesso( lock)
    Requer liberação

Problemas disso:

Quando uma exceção ocorre entre a aquisição é a liberação de recursos(normalmente no construtor):

FILE *A=fopen(na,"w");
// ERRO!!! Uma exceção é lançada aqui sempre!!
fclose(A); // Nunca vai fechar isso!!

Então, como podemos fazer com que o recurso seja liberado quando for adquirido e tenha uma exceção antes de liberar o recurso?

Opção 1:

Uso direto do “try-catch“:

FILE* A=fopen(na,"w");
try{
	//ERRO, aqui sera sempre lançada uma exceção maligna!!
}catch( ... ){
	fclose(A); // Fecha o recurso caso exceção seja lançada.
	throw; // Relança a exceção que veio, caso você não queira trata-la.
}
fclose(A); // Fecha arquivo se não ocorrer a exceção.

Resolve, mas porque fica feio?

  1. Deselegante
  2. Código mais complexo
  3. Mais propenso a erro
  4. Código mais verboso

Opção 2 (e preferível):

Usar objetos via construtor e destrutor, usando o conceito de “RAII”(Gerencia de Recursos é Inicialização):

class ptr_arq {
		FILE* p;
	public:
		ptr_arq( const char* name, const char* mode){
			p=fopen( name, mode); // Inicializa o objeto quando ele é construído
		}
... // Métodos Read, write e gets aqui....
		~ptr_arq(){
			//Libera o recurso(Fecha arquivo) quando ele sai do escopo ou e destruído.
			fclose(A);
		}
};

No código acima, tudo é inline. Então, não há nenhum overhead em todas as chamadas acima.

Com o código acima, você pode usar o arquivos de forma mais simples e segura assim:

{
	ptr_arq A(name_of_file,"w");
	// Usa o arquivo representado por "A</span>" sem se preocupar em fechar e quando fechar.
}	// Fecha arquivo auto-magicamente aqui, por causa do destrutor.

Ao terminar a execução desse escopo, seja normal ou por uma exceção, o processo de limpeza destrói o objeto “A” e executa o destrutor de “A“. Portanto fecha arquivo aberto pelo objeto “A“.

ps:. A classe acima é muito parecida com uma classe já existente de c++, “fstream“… Use ela…

Com isso você usa objetos locais para gerenciar recursos. Isso permite que você escreva código mais limpo e mais simples de usar também. O conceito de adquirir recursos na construção e desalocar recursos na destruição de objetos é chamada de RAII(“Resource Acquisition Is Initialization” ou “Aquisição de Recursos é Inicialização”). Essa técnica usa o construtor e o destrutor e sua interação para gerenciar recursos, deixando o código seguro a exceções.

Questões:

  • Objeto é considerado construído apenas se seu construtoré executado completamente.
    Só neste caso o destrutor do objeto sera executado, pelo processo de limpeza de escopo.
  • Usa-se “RAII” também para sub-objetos, para evitar objetos meio-construídos.

Exemplo de não ser RAII:

class MyFoo{
		int *p;
		void init();
	public:
		MyFoo(int s){
			p=new int[s];
			init();
		}
		~MyFoo(){
			delete []p;
		}
};

No código acima, se o método init() disparar uma exceção, “p” será liberado e a memoria alocada será perdida. Nesse momento, você ganhara um memory leak!

Você pode resolver isso do seguinte método:

class MyFoo{
		vector<int> p;
		void init();
	public:
		MyFoo(int s) : p(s) {
			init();
		}
};

Caso init() dispare uma exceção, “p” estará completamente construído e o destrutor de vector<int> será executado também.

Esse exemplo reforça o fato de usar objetos de “c++“, que sequem firmemente o conceito de “RAII”. Com esses objetos você consegue construir classes que são seguras e tem comportamentos bem definidos e fáceis de usar.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: