A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Eiji Adachi Barbosa LES / DI / PUC-Rio Setembro / 2011 Aula 15 Tratamento de Exceções.

Apresentações semelhantes


Apresentação em tema: "Eiji Adachi Barbosa LES / DI / PUC-Rio Setembro / 2011 Aula 15 Tratamento de Exceções."— Transcrição da apresentação:

1 Eiji Adachi Barbosa LES / DI / PUC-Rio Setembro / 2011 Aula 15 Tratamento de Exceções

2 Avisos Próxima aula ( 3/outubro/2011 ) haverá exercício em sala de aula valendo ponto –Apenas o conteúdo da aula de hoje –Exercício em dupla –Sem consulta janeiro de 142 Eiji Adachi Barbosa

3 Sumário Definições básicas –O que é função? –Por que / para que usar funções? –Como se encerram as funções? –Problema: e quando funções não se encerram corretamente? Tratamento de exceções –Tipos de tratadores –Caso de insucesso –Como tratar exceções Em C Em linguagens de programação contemporâneas janeiro de 143 Eiji Adachi Barbosa

4 Definições básicas O que é uma função? –Função é uma porção auto-contida de código que: possui um nome que pode ser chamado (ativado) de diversos lugares pode retornar zero ou mais valores pode depender de e alterar zero ou mais parâmetros pode alterar zero ou mais valores do estado do módulo –variáveis internas –variáveis globais pode criar, ler e destruir arquivos, etc... TIPO_RETORNO NOME_FUNCAO ( LISTA_PARAMETROS) { CORPO_FUNCAO } janeiro de 144 Eiji Adachi Barbosa

5 Definições básicas Por que / para que usar funções? –Princípio dividir para conquistar Dividir sistema em módulos Dividir algoritmo em funções Evitar códigos monolíticos –Reuso e manutenibilidade janeiro de 145 Eiji Adachi Barbosa

6 Definições básicas Encerrando a execução de uma função: –Chegar ao fim de uma função void –O comando return 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 é local, i.e., após o return o controle do fluxo de execução 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 streams 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 1.` janeiro de 146 Eiji Adachi Barbosa

7 Definições básicas - Pilha de chamadas int main() void firstCall() int printf(const char *...) int main() { firstCall(); return 0; } void firstCall(){ printf("First Call\n"); secondCall(); return; } int secondCall(){ printf("Second Call\n"); thirdCall(); return 0; } char thirdCall(){ printf("Third Call\nOK, Thats enough.\n"); return '0; } janeiro de 147 Eiji Adachi Barbosa

8 int main() { firstCall(); return 0; } void firstCall(){ printf("First Call\n"); secondCall(); return; } int secondCall(){ printf("Second Call\n"); thirdCall(); return 0; } char thirdCall(){ printf("Third Call\nOK, Thats enough.\n"); return '0; } Definições básicas - Pilha de chamadas int main() void firstCall() int secondCall() int printf(const char *...) janeiro de 148 Eiji Adachi Barbosa

9 int main() { firstCall(); return 0; } void firstCall(){ printf("First Call\n"); secondCall(); return; } int secondCall(){ printf("Second Call\n"); thirdCall(); return 0; } char thirdCall(){ printf("Third Call\nOK, Thats enough.\n"); return '0; } Definições básicas - Pilha de chamadas int main() void firstCall() int secondCall() char thirdCall() int printf(const char *...) janeiro de 149 Eiji Adachi Barbosa

10 Problema E o que fazer quando uma condição excepcional (também chamada de exceção) impede que uma função encerre sua execução corretamente? Exemplos: –Não há memória disponível quando você tenta alocar memória dinamicamente –Um parâmetro de entrada ocasiona uma divisão por zero –Hardware pára de funcionar corretamente 25/1/201410 Eiji Adachi Barbosa

11 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 imprevisíveis 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... Tratamento de exceções é o mecanismo responsável pela detecção de condições excepcionais e pela associação de ações corretivas com condições excepcionais 25/1/201411 Eiji Adachi Barbosa

12 Tratamento de exceções Por que é importante tratar exceções? –Você pode irritar o seu usuário janeiro de 1412 Eiji Adachi Barbosa

13 Tratamento de exceções Por que é importante tratar exceções? –Você pode irritar o seu usuário janeiro de 1413 Eiji Adachi Barbosa

14 Tratamento de exceções Por que é importante tratar exceções? –Os usuários podem perder a confiança no seu produto –... e você pode passar uma tremenda vergonha! janeiro de 1414 Eiji Adachi Barbosa

15 Tratamento de exceções Vídeo do Bill Gates: –http://www.youtube.com/watch?v=TrAD25V7ll8http://www.youtube.com/watch?v=TrAD25V7ll8 janeiro de 1415 Eiji Adachi Barbosa

16 Tratamento de exceções Por que é importante tratar exceções? –Pode custar milhões de dólares/reais/euros –Ou até mesmo vidas –http://www.devtopics.com/20-famous-software-disasters/ janeiro de 1416 Eiji Adachi Barbosa

17 Tratamento de exceções janeiro de 1417 Eiji Adachi Barbosa Vídeo do Ariane 5: –http://www.youtube.com/watch?v=kYUrqdUyEpIhttp://www.youtube.com/watch?v=kYUrqdUyEpI

18 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 janeiro de 1418 Eiji Adachi Barbosa

19 Tratamento de exceções Terminologia básica –Exceção: Uma exceção (ou condição excepcional) é um evento que ocorre durante a execução de um programa (ou módulo) e que impede a sua execução normal –Tratador: Um tratador é um conjunto de ações que visam lidar com uma exceção janeiro de 1419 Eiji Adachi Barbosa

20 Tratamento de exceções Exemplos de tratadores: –Armazenamento de erro: cria um registro da exceção e de informações adicionais em arquivo especial (log). –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. –Reconfiguração: reconfigura o estado do sistema com outros valores. –Nova tentativa: a mesma função, ou uma diferente implementação, é invocada novamente. –Liberação de recursos: assegura a liberação de recursos alocados, como memória alocada dinamicamente, arquivos e conexões abertos, etc. –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. –Delegação de controle: delega o controle da execução para outro trecho do sistema mais apto a lidar com a exceção. janeiro de 1420 Eiji Adachi Barbosa

21 Tratamento de exceções Exemplos de tratadores: –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 o acoplamento. –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. –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. janeiro de 1421 Eiji Adachi Barbosa

22 Como tratar exceções? 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, usaremos nesta disciplina um idioma de tratamento de exceções: –Usando o código de retorno das funções e elementos enum para indicar sob qual condição a função encerrou sua execução –Modificando / testando variáveis globais ou parâmetros passados por referência janeiro de 1422 Eiji Adachi Barbosa

23 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 janeiro de 1423 Eiji Adachi Barbosa

24 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 ; } /* Fim função: LIS &Excluir elemento */ janeiro de 1424 Eiji Adachi Barbosa

25 Usando o código de retorno das funções int main(void){... LIS_tpCondRet condRet = InserirElementoAntes( lista, pValor ); switch( condRet ) { case LIS_CondRetFaltouMemoria:... case LIS_CondRetOK:... default : printf(Condição de retorno inesperada); } janeiro de 1425 Eiji Adachi Barbosa

26 Usando o código de retorno das funções Problemas –Uma função pode usar uma condição de retorno excepcional cujo valor reside dentro do intervalo de valores válidos calculados pela função. O problema é que a função chamadora não sabe se o valor retornado é um valor válido ou uma condição excepcional 25/1/201426 Eiji Adachi Barbosa

27 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 25/1/201427 Eiji Adachi Barbosa 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; }

28 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 janeiro de 1428 Eiji Adachi Barbosa

29 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 ; } /* Fim função: LIS &Excluir elemento */ Usar uma variável global, seria análogo... janeiro de 1429 Eiji Adachi Barbosa

30 Usando parâmetro passado por referência int main(void){... char *errorMsg; LIS_tpCondRet condRet = InserirElementoAntes( lista, pValor, &errorMsg ); switch( condRet ) { case LIS_CondRetFaltouMemoria: printf( %s, errorMSG ); case LIS_CondRetOK:... default : printf(Condição de retorno inesperada); } Usar uma variável global, seria análogo... janeiro de 1430 Eiji Adachi Barbosa

31 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 Nem sempre é possível retornar um elemento enumerado como condição de retorno –Ex.: Implemente uma função que receba os três parâmetros (Nome, Estado Civil, Idade) e retorne por referência a estrutura preenchida. Como prover mais informações a respeito do problema / exceção? –Ex.: Qual a severidade? Que condições levaram a esta ocorrência? janeiro de 1431 Eiji Adachi Barbosa

32 Limitações de C Há um overhead na criação de tipos enumerados para 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ção depende 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ódigo de tratamento de exceção –Código torna-se rapidamente extenso, complexo e pouco compreensível janeiro de 1432 Eiji Adachi Barbosa

33 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 –FINALLY – define um trecho de código que sempre será executado, mesmo quando exceções ocorrerem –THROW – sinaliza a ocorrência de uma exceção –THROWS – especifica na interface de um módulo / função quais as possíveis exceções que podem ser ocasionadas durante a execução daquele módulo / função janeiro de 1433 Eiji Adachi Barbosa

34 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, PermissionException; janeiro de 1434 Eiji Adachi Barbosa

35 Sinalização explícita de exceções Cláusula throw sinaliza a ocorrência de uma exceção static void escreveArquivo(Arquivo a) throws FileNotFoundException, CharCodingException, PermissionException { Buffer bf = buscaArquivo( a ); if( bf == null ) throw new FileNotFoundException(); } janeiro de 1435 Eiji Adachi Barbosa

36 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 ){...} } janeiro de 1436 Eiji Adachi Barbosa

37 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 25/1/201437 Eiji Adachi Barbosa leArquivo(){ try{ abreArquivo(); determineTamanhoArquivo(); aloqueMemoria(); copieDados(); } catch( abrirErro ){...} catch( determinarTamanhoErro ) {...} catch( alocarMemoriaErro ) {...} catch( copiarDadosErro ) {...} finally { try{ fecheArquivo(); } catch( fecharArquivoErro ){...} }

38 Lista preencheLista(){ Arquivo arq = null; Lista lista = null; try{ arq = abreArquivo( Dados.txt ); lista = criaLista(); for( i=0; i<SIZE; i++ ){ adiciona( lista, arq, i ); } //faz mais alguma coisa } catch( RegistroException ){ print( Registro lido incorretamente ); } finally { if( arq != null){ fechaArquivo( arq ); } return lista; } void adiciona(Lista lista, Arquivo arq, int i ) throws RegistroException { Registro r = leRegistro( arq, i ); Elemento e = criaElement( r ); adicionaElemento( lista, e, i ); } Execução e transferência não-local preecheLista() finally catch( RegistroException ) janeiro de 1438 Eiji Adachi Barbosa

39 Lista preencheLista(){ Arquivo arq = null; Lista lista = null; try{ arq = abreArquivo( Dados.txt ); lista = criaLista(); for( i=0; i<SIZE; i++ ){ adiciona( lista, arq, i ); } //faz mais alguma coisa } catch( RegistroException ){ print( Registro lido incorretamente ); } finally { if( arq != null){ fechaArquivo( arq ); } return lista; } void adiciona(Lista lista, Arquivo arq, int i ) throws RegistroException { Registro r = leRegistro( arq, i ); Elemento e = criaElement( r ); adicionaElemento( lista, e, i ); } Execução e transferência não-local preecheLista() finally catch( RegistroException ) abreArquivo janeiro de 1439 Eiji Adachi Barbosa

40 Lista preencheLista(){ Arquivo arq = null; Lista lista = null; try{ arq = abreArquivo( Dados.txt ); lista = criaLista(); for( i=0; i<SIZE; i++ ){ adiciona( lista, arq, i ); } //faz mais alguma coisa } catch( RegistroException ){ print( Registro lido incorretamente ); } finally { if( arq != null){ fechaArquivo( arq ); } return lista; } void adiciona(Lista lista, Arquivo arq, int i ) throws RegistroException { Registro r = leRegistro( arq, i ); Elemento e = criaElement( r ); adicionaElemento( lista, e, i ); } Execução e transferência não-local preecheLista() finally catch( RegistroException ) criaLista janeiro de 1440 Eiji Adachi Barbosa

41 Lista preencheLista(){ Arquivo arq = null; Lista lista = null; try{ arq = abreArquivo( Dados.txt ); lista = criaLista(); for( i=0; i<SIZE; i++ ){ adiciona( lista, arq, i ); } //faz mais alguma coisa } catch( RegistroException ){ print( Registro lido incorretamente ); } finally { if( arq != null){ fechaArquivo( arq ); } return lista; } void adiciona(Lista lista, Arquivo arq, int i ) throws RegistroException { Registro r = leRegistro( arq, i ); Elemento e = criaElement( r ); adicionaElemento( lista, e, i ); } Execução e transferência não-local preecheLista() finally catch( RegistroException ) adiciona leRegistro janeiro de 1441 Eiji Adachi Barbosa

42 Lista preencheLista(){ Arquivo arq = null; Lista lista = null; try{ arq = abreArquivo( Dados.txt ); lista = criaLista(); for( i=0; i<SIZE; i++ ){ adiciona( lista, arq, i ); } //faz mais alguma coisa } catch( RegistroException ){ print( Registro lido incorretamente ); } finally { if( arq != null){ fechaArquivo( arq ); } return lista; } void adiciona(Lista lista, Arquivo arq, int i ) throws RegistroException { Registro r = leRegistro( arq, i ); Elemento e = criaElement( r ); adicionaElemento( lista, e, i ); } Execução e transferência não-local preecheLista() finally catch( RegistroException ) adiciona leRegistro Esse trecho de código não é executado! janeiro de 1442 Eiji Adachi Barbosa

43 Lista preencheLista(){ Arquivo arq = null; Lista lista = null; try{ arq = abreArquivo( Dados.txt ); lista = criaLista(); for( i=0; i<SIZE; i++ ){ adiciona( lista, arq, i ); } //faz mais alguma coisa } catch( RegistroException ){ print( Registro lido incorretamente ); } finally { if( arq != null){ fechaArquivo( arq ); } return lista; } void adiciona(Lista lista, Arquivo arq, int i ) throws RegistroException { Registro r = leRegistro( arq, i ); Elemento e = criaElement( r ); adicionaElemento( lista, e, i ); } Execução e transferência não-local preecheLista() finally print Esse trecho de código não é executado! catch( RegistroException ) janeiro de 1443 Eiji Adachi Barbosa

44 Lista preencheLista(){ Arquivo arq = null; Lista lista = null; try{ arq = abreArquivo( Dados.txt ); lista = criaLista(); for( i=0; i<SIZE; i++ ){ adiciona( lista, arq, i ); } //faz mais alguma coisa } catch( RegistroException ){ print( Registro lido incorretamente ); } finally { if( arq != null){ fechaArquivo( arq ); } return lista; } void adiciona(Lista lista, Arquivo arq, int i ) throws RegistroException { Registro r = leRegistro( arq, i ); Elemento e = criaElement( r ); adicionaElemento( lista, e, i ); } Execução e transferência não-local preecheLista() finally fechaArquivo Esse trecho de código não é executado! janeiro de 1444 Eiji Adachi Barbosa

45 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 –Liberação de recursos 25/1/201445 Eiji Adachi Barbosa

46 Referência Cap. 8 do livro Programação Modular http://download.oracle.com/javase/tutorial/essential/exceptions/in dex.html janeiro de 1446 Eiji Adachi Barbosa

47 FIM janeiro de 1447 Eiji Adachi Barbosa


Carregar ppt "Eiji Adachi Barbosa LES / DI / PUC-Rio Setembro / 2011 Aula 15 Tratamento de Exceções."

Apresentações semelhantes


Anúncios Google