• Nenhum resultado encontrado

Aula 22 Tratamento de Exceções

N/A
N/A
Protected

Academic year: 2021

Share "Aula 22 Tratamento de Exceções"

Copied!
22
0
0

Texto

(1)

Alessandro Garcia LES / DI / PUC-Rio Junho / 2016

Aula 22

Tratamento de Exceções

Avisos

• Trabalho T4 – enunciado completo está disponível:

– devem estar em andamento: • conclusão da implementação do jogo

• agora: teste do módulo Lista deve satisfazer critério de cobertura de arestas

– entrega: até 30/6

• Prova P2: 22/6

(2)

Sumário

• Definições básicas

– Como se encerram as funções?

– Problema: e quando funções não encerram corretamente?

• Tratamento de exceções

– Tipos de tratadores – Como tratar exceções

• Em C

• Em linguagens de programação contemporâneas

2

Relembrando - Definições básicas

• O que é uma função?

– Funçãoé uma porção auto-contida de código que:

• possui um nomeque pode ser chamado (ativado) de diversos lugares

• pode retornarzero ou mais valores

• pode depender de e alterar zero ou mais parâmetros

• pode alterarzero ou mais valores do estadodo módulo

– variáveis internas – variáveis globais

• pode criar, ler e destruir arquivos, etc...

TIPO_RETORNO NOME_FUNCAO ( LISTA_PARAMETROS) {

CORPO_FUNCAO }

(3)

• Encerrando a execução de uma função:

– Chegar ao fim de uma função void

– O comando return <VALUE>

• Encerra a execução de uma função imediatamente

Se um valor de retorno é informado, a função chamada (callee) retorna este valor para a função chamadora (caller)

A transferência de controle após o return passa da função chamada para a função chamadora

– O comando exit(int)

• Encerra a execução do programa

1. Executa em ordem reversa todas as funções registradas pela função int atexit( void (*func)(void) )

2. Todos arquivos são fechados, todos arquivos temporários são apagados

3. O controle de execução retorna ao ambiente-hospedeiro (host enviornment) o valor inteiro passado como argumento

4

Problema

Exceção: Uma exceção é um evento que ocorre durante a

execução de um programa (ou módulo) e que impede a sua execução normal

• E o que fazer quando uma exceção impede que uma função encerre sua execução corretamente?

(4)

Problema

• Exemplos:

– Um parâmetro de entrada ocasiona uma divisão por zero – Um valor de um dos parâmetros ou variáveis viola assertivas

de entrada, saída

– Uma das assertivas estruturais é violada

– Não há memória disponível quando você tenta alocar memória dinamicamente

– Hardware para de funcionar corretamente

6

Tratamento de exceções

• Por que é importante tratar exceções?

(5)

• Por que é importante tratar exceções?

– Os usuários podem perder a confiança no seu produto – ... e você pode passar uma tremenda vergonha!

8

Tratamento de exceções

• Sistemas atuais são cada vez maiores e mais complexos

– Condições excepcionais podem surgir por diversos motivos e serem até mesmo difíceis de serem previstas

• Sistemas robustos e confiáveis devem prover seus serviços mesmo sob condições excepcionais

– Sistemas críticos: • Sistemas bancários

• Controladores de redes elétricas, vôo, usinas nucleares...

• Sistemas embarcados em aviões, submarinos, foguetes... • O tratamento de exceções é parte central do

(6)

Tratamento de exceções - Caso de insucesso

Em outubro de 1996 o foguete francês Ariane 501 se

autodestruiu 5 minutos após decolar

Motivo:

– cálculo errado do ângulo de ataque

Causa:

– O Ariane 5 reutilizou um módulo do Ariane 4 para calcular o “Alinhamento Interno”, elemento relacionado com a

componente horizontal da velocidade

– O valor gerado pelo módulo do Ariane 4 foi muito maior do que o esperado pelo módulo do Ariane 5, pois a trajetória do Ariane 5 difere da trajetória do Ariane 4

– O módulo do Ariane 5 tentou converter o valor do

“Alinhamento Interno”de um número de 64 bits em ponto

flutuante para um inteiro de 16 bits com sinal

– Valor em ponto flutuante era maior do que poderia ser representado por um inteiro

– Operação de conversão não estava protegida e ocasionou Overflow Exception

10

Tratamento de exceções

• Vídeo do Bill Gates:

– http://www.youtube.com/watch?v=TrAD25V7ll8

• Vídeo do Ariane 5:

– http://www.youtube.com/watch?v=kYUrqdUyEpI

• Outros desastres famosos devido ao não tratamento de exceções

(7)

• Por que é importante tratar exceções?

– Pode custar milhões de dólares/reais/euros – Ou até mesmo vidas

12

Tratamento de exceções - Terminologia

Exceção: Uma exceção é um evento que ocorre durante a execução de um programa (ou módulo) e que impede a sua execução normal

– Uma exceção indica que o estado interno do sistema está inconsistente e, por isso, não é possível prosseguir com sua execução normal

– Para restaurar a consistência interna do sistema, é necessário tomar ações corretivas, ou remediadoras

Tratador: Um tratador é um conjunto de ações que visam corrigir ou remediar a ocorrência de uma exceção

Mecanismo de tratamento de exceções: Um mecanismo de tratamento de exceções é um modelo que permite a

desenvolvedores:

– Representar os tipos de ocorrências de exceção

– Indicar a ocorrência de uma exceção na interface de funções/módulos

– Detectar a ocorrência de uma exceção na execução da função

– Estruturar ações de tratamento de exceções

(8)

Maio 2009 Alessandro Garcia © LES/DI/PUC-Rio 14 / 32

Estrutura de uma função

• Conjunto de exceções sinalizadas na interface – em C: condições de retorno excepcionais

– Exceções – exs.: nome de arquivo não existe, índice/chave fora do limite, conexão com servidor/banco-dados não pode ser estabelecida, etc...

Tratador E1 Tratador E2 Tratador E3

Função

Chamadas Chamadas

Tratamento de exceções

• Exemplos de tratadores:

Ignora a exceção: identifica a ocorrência de uma exceção e não toma nenhuma ação corretiva. Má prática e deve ser evitada.

Re-sinaliza a exceção: identifica um tipo de exceção e reporta para a função chamadora outro tipo de exceção. Geralmente é usada para preservar abstração e encapsulamento.

Delegação de controle: delega o controle da execução para outro módulo do sistema mais apto a lidar com a exceção.

Notificação ao usuário: notifica o usuário a ocorrência da exceção, com possibilidade de pedir novo input, caso seja possível.

Preferencialmente, somente em casos que usuário deve ser envolvido.

Armazenamento de erro: cria um registro da exceção e de informações adicionais em arquivo especial (log).

Reconfiguração: reconfigura o estado do sistema com outros valores.Nova tentativa: a mesma função é simplesmente invocada

(9)

• Exemplos de tratadores:

Liberação de recursos: assegura a liberação de recursos alocados, como memória alocada dinamicamente, arquivos e conexões abertos, etc.

Preparação para desligar: prepara o sistema para terminar sem causar efeitos colaterais. Geralmente é usada em situações

extremas.É necessário liberar todos os recursos alocados e reverter o sistema para um estado em que os dados estão consistentes.

Recuperação por retrocesso: desfaz modificações no estado do sistema a fim de restaurá-lo a um estado válido. Comumente usado em sistemas de bancos de dados.

Uso de redundância de software: ativa uma função com o mesmo propósito.

Uso de redundância de dados: uso de elementos adicionais da estrutura que permitam navegar de outras formas na estrutura. Vide estruturas auto-verificáveis.

16

Como tratar exceções em módulos em C?

• A linguagem C não traz suporte específico para tratamento de exceções

• Fica sob responsabilidade do programador desenvolver uma forma de identificar e tratar exceções da aplicação

• Existem várias formas de realizar esta tarefa, cada um com seus prós e contras

• A fim de padronizar a identificação e o tratamento de exceções em C, usamos nesta disciplina

padrões/convenções de tratamento de exceções:

Tipos enum e código de retorno das funções para indicar sob qual condição a função encerrou sua execução

– Se necessários, define-se parâmetros adicionais passados por referência e modifica-se seus valores para informações extra do erro

(10)

Usando o código de retorno das funções

• Este é o método mais comum e mais simples de tratamento de exceções em linguagem C

• Neste método, as funções tem duas responsabilidades:

A função chamada deve usar o comando return para indicar sob qual condição (normal | excepcional) sua execução encerrou

A função chamadora deve testar o código retornado pela função chamada a fim de tomar ações corretivas, caso necessário

Preferencialmente, as condições de retorno devem ser declaradas como um elemento enum

18

Usando o código de retorno das funções

typedef enum {

LIS_CondRetOK ,

/* Concluiu corretamente */ LIS_CondRetListaVazia ,

/* A lista não contém elementos */ LIS_CondRetFimLista ,

/* Foi atingido o fim de lista */ LIS_CondRetNaoAchou ,

/* Não encontrou o valor procurado */ LIS_CondRetFaltouMemoria

/* Faltou memória ao tentar criar um elemento de lista */

} LIS_tpCondRet ;

LIS_tpCondRet LIS_InserirElementoAntes

( LIS_tppLista pLista , void * pValor ) {

tpElemLista * pElem ;

pElem = CriarElemento( pLista , pValor ) ; if ( pElem == NULL ) {

return LIS_CondRetFaltouMemoria ;

} /* if */ ....

return LIS_CondRetOK ;

(11)

int main(void){ ...

LIS_tpCondRetcondRet= InserirElementoAntes( lista, pValor ); switch( condRet) { case LIS_CondRetFaltouMemoria: ... case LIS_CondRetOK: ... default :

printf(“Condição de retorno inesperada”); }

}

20

Usando parâmetro passado por referência

LIS_tpCondRet LIS_InserirElementoAntes

( LIS_tppLista pLista , void * pValor, char ** errorMsg ) {

tpElemLista * pElem ;

pElem = CriarElemento( pLista , pValor ) ; if ( pElem == NULL ) {

char str[] = “Não foi possível alocar memória para um novo elemento”; int size = strlen( str ) + 1;

(*errorMsg) = (char*)malloc( sizeof(char) * size ); memcpy( (*errorMsg), str, size );

return LIS_CondRetFaltouMemoria ;

} /* if */ ....

return LIS_CondRetOK ;

(12)

Maio 2009 Alessandro Garcia © LES/DI/PUC-Rio 22 / 32

Exemplo de condição de retorno

• Servidor

typedef enum {

CondRetLeuOK , /* Leitura normal */

CondRetLeuEOF , /* Encontrou fim de arquivo antes de ler */ CondRetLeuErro /* Ocorreu erro de leitura */

} tpCondRetLeu ;

. . .

tpCondRetLeu LerReg( FILE * pArq , tpReg * pReg ) {

if ( feof( pArq )) {

memset( pReg , 0xFF , sizeof( tpReg )) ; return CondRetLeuEOF ;

} /* if */

Conta = fread( pReg , pArq , sizeof( tpReg ) , 1 ) ; if ( ( ferror( pArq ) != 0 ) || ( Conta != 1 )) {

memset( pReg , 0xCC , sizeof( tpReg )) ; return CondRetLeuErro ;

} /* if */

return CondRetLeuOK ; } /* Função LerReg */

Exemplo de condição de retorno

• A função cliente contém o código:

Cond = LerReg( pArqA , pBuffer ) ; switch ( Cond )

{

case CondRetLeuOK :

/* código que trata o caso de leitura normal */ break ;

case CondRetLeuEOF :

/* código que trata o caso de fim de arquivo */ break ;

case CondRetLeuErro :

printf( "\nErro de leitura no arquivo: %s código \'C\' %c" , NomeArqA , errno ) ;

printf( "\nPrograma será cancelado" ) ; Finalizar( CondRetLeuErro ) ;

default:

printf( "\Erro de execução: LerReg condição desconhecida: %i" , Cond ) ;

printf( "\nPrograma será cancelado" ) ; Finalizar( ErroDesconhecido ) ; } /* fim switch */ o break é desnecessário, pois Finalizar( ) não retorna

(13)

int main(void){ ...

char *errorMsg;

LIS_tpCondRetcondRet= InserirElementoAntes( lista, pValor, &errorMsg); switch( condRet) { case LIS_CondRetFaltouMemoria: printf( “%s”, errorMSG); case LIS_CondRetOK: ... default :

printf(“Condição de retorno inesperada”); }

}

24

Usando variáveis globais ou parâmetros

• Este método é complementar ao método de condições de retorno

– Bastante usado na GLIBC, biblioteca padrão do sistema GNU/Linux

• Neste método, as funções tem as seguintes responsabilidades:

– A função chamada deve modificar variáveis globais ou parâmetros passados por referência para indicar sob qual condição (normal | excepcional) sua execução encerrou – A função chamadora deve testar a variável global, ou o parâmetro passado por referência, a fim de tomar ações corretivas, caso necessário

(14)

Limitações de C

• A sinalização de uma exceção não é explícita

Usa-se o comando return, parâmetros passados por referência ou variáveis globais

– Não há distinção entre encerramento sob condição normal ou excepcional

• O sistema não é interrompido no momento em que a exceção ocorre

– Mesmo sabendo-se que o estado é inconsistente

• Como prover mais informações a respeito do problema / exceção?

Ex.: Qual a severidade? Que condições levaram a esta ocorrência?

– Uso de parâmetros encoraja quebra de abstração e encapsulamento

26

Limitações de C

Há um overheadna criação de tipos enumeradospara cada módulo

– Para cada módulo é definido um tipo enumerado, mesmo que representem a mesma condição(EX.: Falta de memória)

• A associação entre as exceções descritas nos tipos enumerados e quais exceções que podem ser levantadas por uma funçãodepende exclusivamente da especificação da função

– Difícil entender o acoplamento excepcional entre funções: quais exceções devem ser tratadas?

Não há separação textual do códigode tratamento de exceção

– Código torna-se rapidamente extenso, complexo e pouco compreensível

(15)

Maio 2009 Alessandro Garcia © LES/DI/PUC-Rio 28 / 32

• Comportamento exceptional de funções

– diferente de C, C++ e Java provêem suporte explícito a tratamento de exceções

Facilidades / Mecanismos para Tratamento de Exceções

Exceções Tratadores (Handlers)

Desvio do Fluxo e Busca de Tratadores

Definição de “Regiões Protegidas” Interfaces

Excepcionais

Usando o código de retorno das funções

Problemas:

– Chamadas encadeadas de funções podem resultar em uma estrutura muito

aninhada que é difícil de compreender, testar e fazer a manutenção ARQ_tpCondRet leArquivo(){ condRet = OK; abreArquivo(); se( arquivoAberto() ){ determineTamanhoArquivo(); se( determinouTamanho() ){ aloqueMemoria(); se( alocouMemoria() ){ copieDados(); se( ! copiouDados() ){ condRet = ERRO_COPIAR_DADOS; } } senão { condRet = ERRO_ALOCAR_MEM; } } senão { condRet = ERRO_DET_TAM; } fecheArquivo(); se( ! fechouArquivo() ){ condRet = ERRO_FECHAR_ARQ; } } senão { condRet = ERRO_ABRIR_ARQ; } }

(16)

Linguagens contemporâneas

• Linguagens como Java, JavaScript, C++, C#, Python ... proveem mecanismos de tratamento de exceções implementados na própria linguagem

• Elementos sintáticos específicos para tratamento de exceções:

THROW – sinaliza a ocorrência de uma exceção

TRY – define uma região protegida contra a ocorrência de exceções

CATCH – define um tratador, i.e., um trecho de código que implementa um conjunto de ações de recuperação

30

Sinalização explícita de exceções

Cláusula throw sinaliza a ocorrência de uma exceção

static void escreveArquivo(Arquivo a) ... { ...

Buffer bf = buscaArquivo( a ); if( bf == null )

throw new FileNotFoundException(); }

(17)

Maio 2009 Alessandro Garcia © LES/DI/PUC-Rio 32 / 32

• Exceções são levantadas/sinalizadas explicitamente

int funcaoX ( ...) { // código desprotegido try {

// código a ser tentado; região protegida if (x > 10) {throw excecao};

}

catch (Excecao) {

// código do tratador: a ser executado // em caso de exceção if (x > 10) {throw excecao2}; } } acoplamento: exceção sinalizada

Linguagens contemporâneas

• Linguagens como Java, JavaScript, C++, C#, Python ... provêem mecanismos de tratamento de exceções implementados na própria linguagem

• Elementos sintáticos específicos para tratamento de exceções:

TRY – define uma região protegida contra a ocorrência de exceções

CATCH – define um tratador, i.e., um trecho de código que implementa um conjunto de ações de recuperação

THROW – sinaliza a ocorrência de uma exceção

THROWS – especifica na interface de uma função quais as possíveis exceções que podem ser ocasionadas durante a execução daquela função do módulo

(18)

Maio 2009 Alessandro Garcia © LES/DI/PUC-Rio 34 / 32

Estrutura de uma função em Java

• Acoplamento – conjunto de exceções sinalizadas – exceções são sinalizadas explicitamente em Java

acoplamento: exceção sinalizada

class Count {

public static void main(String args[]) throws java.io.IOException

{ int count = 0; while (System.in.read() != -1) count++; System.out.println("Entrada:"+count+ "caracteres."); } }

Acoplamento excepcional explícito

Cláusula throws indica quais exceções podem ocorrer durante a execução de uma função

void escreveArquivo(Arquivo) throws FileNotFoundException,

CharCodingException,

(19)

• Linguagens como Java, JavaScript, C++, C#, Python ... provêem mecanismos de tratamento de exceções implementados na própria linguagem

• Elementos sintáticos específicos para tratamento de exceções:

TRY – define uma região protegida contra a ocorrência de exceções

CATCH – define um tratador, i.e., um trecho de código que implementa um conjunto de ações de recuperação

THROW – sinaliza a ocorrência de uma exceção

THROWS – especifica na interface de uma função quais as possíveis exceções que podem ser ocasionadas durante a execução daquela função do módulo

FINALLY – define um trecho de código que sempre será executado, mesmo quando exceções ocorrerem

36

Mecanismo para

código de limpeza

• O código definido no bloco

finally sempre será

executado, seja após a terminação normal, ou após a terminação

excepcional, de um bloco

try

– Usado especialmente para liberação de recursos, como memória, arquivos abertos, conexões abertas, etc leArquivo(){ try{ abreArquivo(); determineTamanhoArquivo(); aloqueMemoria(); copieDados(); } catch( abrirErro ){...} catch( determinarTamanhoErro ) {...} catch( alocarMemoriaErro ) {...} catch( copiarDadosErro ) {...} finally { try{ fecheArquivo(); } catch( fecharArquivoErro ){...} } }

(20)

Melhor separação textual

ARQ_tpCondRet leArquivo(){ condRet = OK; abreArquivo(); se( arquivoAberto() ){ determineTamanhoArquivo(); se( determinouTamanho() ){ aloqueMemoria(); se( alocouMemoria() ){ copieDados(); se( ! copiouDados() ){ condRet = ERRO_COPIAR_DADOS; } } senão { condRet = ERRO_ALOCAR_MEM; } } senão { condRet = ERRO_DET_TAM; } fecheArquivo(); se( ! fechouArquivo() ){ condRet = ERRO_FECHAR_ARQ; } } senão { condRet = ERRO_ABRIR_ARQ; } } leArquivo(){ try{ abreArquivo(); determineTamanhoArquivo(); aloqueMemoria(); copieDados(); } catch( abrirErro ){...} catch( determinarTamanhoErro ) {...} catch( alocarMemoriaErro ) {...} catch( copiarDadosErro ) {...} finally { try{ fecheArquivo(); } catch( fecharArquivoErro ){...} } } 38

Linguagens contemporâneas

• Principais vantagens em relação a C:

Redução do aninhamento de estruturas if-then-else

Melhor separação textual entre o código que implementa a lógica da aplicação e o código que implementa o tratamento de exceções

– Também há uma clara distinção entre o encerramento normal de uma função ( comando return ) e o encerramento excepcional ( comando throw )

Tipos de exceção podem ser reutilizadas entre diferentes módulos

– Mecanismos que garantem a execução de determinados trechos de código tanto em situações normais, quanto em situações excepcionais

Blocos finally

(21)

• Mesmo com os mecanismos de tratamento de exceções providos na própria linguagem, código de tratamento de exceções ainda é fonte de erros:

– Dificuldade em modificar métodos que tratam exceções – Tratadores vazios (catch block vazio)

– Exceções não tratadas

• Erros no código de tratamento de exceções são de difícil diagnose

– Código pouco executado e pouco testado

• Implementar tratamento de exceções não é trivial e requer esforço extra dos desenvolvedores

40

Tratamento de Exceções: Origem

1971

Parnas & Dijkstra Princípio de Encapsulamento e Separação de Interesses 1975 Goodenough EH Notation 1979 CLU Declaração explícita De interface excepcional Tratamento de Exceções em Linguagens Modernas 1980 1964 PL/I ON statements

indicação de ocorrência de exceção associação do tratador

(22)

Referência

• Cap. 8 do livro Programação Modular

• Leitura complementar:

– Tutorial sobre tratamento de exceções em Java

• http://download.oracle.com/javase/tutorial/essential/except ions/index.html

– Artigos

• “Discovering Faults in Idiom-Based Exception Handling”, Bruntink, M., van Deursen, A. and Tourwé, T. In

Proceedings of 28th ICSE, 2006.

• “Exception handling: a field study in Java and .NET”, Cabral, B. and Marques, P. In Proceedings of 21th ECOOP, 2007.

42

Referências

Documentos relacionados

Interessa-nos, particularmente, o apelo de Paulo para as evidências da união dos gálatas com Cristo e, também, para a prova escriturística: o exemplo de Abraão..

(E) Pedro e João terão prescritos os eventuais direitos trabalhistas a partir de dois anos da extinção do referido contrato, mas, se ajuizarem a ação ao

n Por exemplo, imagine que por algum motivo você precisa que uma exceção seja lançada quando a letra “B” ou “b” não existe e determinada frase, como não existe nenhuma

Desta maneira, objetiva-se contribuir para que a medida socioeducativa de privação de liberdade seja, de fato, pedagógica, e não apenas punitiva, para que o

As frequências alélicas HPA variam muito entre grupos populacionais, e, portanto, a seleção de doadores genotipados para os principais polimorfismos dos

Em suas tradições que foram meticulosamente registrada por eruditos muçulmanos, o profeta Muhammad, que Deus o louve, encorajou seus seguidores a buscar conhecimento 4.. Disse

Segundo o grupo europeu de interesse em hipersensibili- dade a drogas (European Network for Drug Allergy – ENDA) da Academia Europeia de Alergia e Imunologia Clínica, são quatro

É através do menu de programações que o usuário aprende e apaga controles remotos e sensores, configura o modo de operação dos relês, altera senha mestre e