Sei sulla pagina 1di 17

H algum tempo venho estudando detalhadamente o tratamento de excees usando Try, Except, Finally e aps encontrar muita coisa

igual na internet resolvi escrever de forma objetiva o uso dessas clusulas ainda ignoradas por alguns desenvolvedores. Nesse artigo no entrarei em detalhes histricos, j irei direto ao ponto. Objetivo desse artigo apresentar: - Problemas que geram excees. - Try, Finally com exemplos. - Try, Except com exemplos. - Try, Except com o tipo de exceo especificado. Repare a figura abaixo:

Eu tenho certeza que todos os desenvolvedores em algum momento da vida j se depararam com a mensagem da figura acima, ou ento, com outras do tipo: List index out of bounds (-1), ou ainda Cannot make a visible window modal. Essas mensagens no so geradas simplesmente pela sua Aplicao ou pelo Delphi, na verdade, elas so excees no tratadas. Para entender melhor, exceo um objeto definido pelo tipo Exception ou uma classe descedente. Sua funo trabalhar especificamente nos casos de anormalidade que podem ocorrer na Aplicao, exemplo: Se tentarmos acessar um ndice no existente no ListBox uma anormalidade ser detectada pela exceo e uma mensagem ser mostrada. Vejamos esse exemplo da forma prtica: Aplicao

Cdigo - Evento OnClick() do Boto "Mostrar".

Com a aplicao em execuo a Exceo mostrada aps o clique no boto "Mostrar"

Anlise No Evento OnClick() do Boto "Mostrar" repare que existem duas linhas com ShowMessage, mas a segunda linha nem chega a ser executada. Esse problema ocorreu porque a Aplicao tentou acessar um ndice inexistente e assim, a exceo detectou uma anormalidade na execuo do primeiro ShowMessage e retornou a mensagem "List index out of bounds(-1)". No Delphi devemos tratar esse tipo de problema utilizando as clusulas Try, Except e Finally. Try - Except - Finally A clusula Try usada para iniciar um bloco que pode conter possveis erros. Se um erro ocorrer, o programa no ser terminado. Instantaneamente, o Try deixa de ser executado e d lugar a clusula Except ou Finally. Try pode ser usado em inmeros trechos do cdigo, podendo at ser aninhado. A clusula Except usada para iniciar um bloco caso uma exceo ocorra em Try. Se o bloco que estiver em Except conter a exceo o programa no ser terminado. A clusula Finally usada para iniciar um bloco havendo problemas ou no com a clusula Try. Verso 1 - Try - Finally Nos trechos de cdigo Try - Finally, a clusula Finally garante que todo o cdigo contido em Finally ser executado independente ou no de problemas no cdigo executado dentro da clusula Try. Em Try - Finally, Finally geralmente usado para permitir limpeza de recursos alocados anteriormente. Exemplo de Implementao Try // Trechos de Cdigo Finally // Trechos de Cdigo End; No exemplo abaixo uma diviso por Zero ocorre sem sucesso em Try exatamente na linha "numero := 1 div zero;" gerando uma exceo que no tratada. Assim, a linha "ShowMessage( 'numero / zero = ' + IntToStr( numero ) );" no executada e o

cdigo dentro da clusula finally executado.

Depois que o trecho de cdigo da clusula finally executado a exceo no tratada retorna a mensagem:

Verso 2 - Try - Except Nos trechos de cdigo Try - Except, somente se a clusula Try gerar uma exceo que a clusula Except ser executada. Except usado para realizar ao alternativa quando algo inesperado ocorrer em Try. A clusula Except por si s, no pode determinar o tipo de erro encontrado. Exemplo de Implementao Try // Trechos de Cdigo Except // Trechos de Cdigo End; No exemplo abaixo uma diviso por Zero ocorre sem sucesso em Try exatamente na linha "numero := 1 div zero;" gerando uma exceo tratada com "ShowMessage('Erro desconhecido encontrado!');". Assim, nenhuma mensagem de exceo mostrada.

Resultado da exceo gerada no exemplo acima

No caso do Except podemos utilizar diferentes aes para diferentes tipos de excees tais como EInOutError. Alm disso, a clusula else pode ser usada para pegar todos os tipos de excees inesperadas, e o Tipo geral Exception usado para pegar todos os tipos de excees. Atribuindo um nome exceo, o texto da mensagem da exceo (Name.Message) pode ser obtido para a exibio, ou ento, para outras finalidades. Quando uma exceo aparece como no prximo exemplo, se a exceo no age sobre sentenas On ou Else, ento uma checagem feita para ver se estamos num bloco Try aninhado. Caso sim, a clusula Except do pai Try processada. Se no, uma clusula On ou Else procurada, e o programa termina. A clusula Else no realmente necessria - melhor usar On E:Exception Do, o tratamento de exceo genrico, j que ele fornece a mensagem de erro (E.Message). Exemplo de Implementao Try // Trechos de Cdigo Except // E : Exception Do On Nome : Tipo da Exceo Do // Trechos de Cdigo Else // opcional // Trechos de Cdigo End; Nota: Voc pode determinar o tipo de erro que ocorreu usando a manipulao de exceo genrica - On E:Exception Do. 'E' um ponteiro ao objeto Exception criado pela

condio de exceo. No exemplo abaixo uma diviso por Zero ocorre sem sucesso em Try exatamente na linha "numero := 1 div zero;" gerando uma exceo tratada de forma que o tipo de exceo seja mostrada, linha on E : Exception do ShowMessage(E.ClassName + 'erro gerado, com mensagem: ' + E.Message');

Resultado da exceo gerada no exemplo acima

Antes de encerrarmos a primeira parte deixo alguns pontos importantes para implementao do Try, except e finally em casos de tratamento de excees. Pontos Importantes Nunca construir tratamento de excees dessa forma: Try ... Except ... Finally ... End; Forma correta de Aninhar tratamento de excees usando Try, Except, Finally: Try

Try ... Except ... End; Finally ... End;

Como, no artigo anterior vimos as clusulas Try, Except e Finally, nesse artigo veremos exemplos de Try, Except e Finally aninhados e tambm apresentaremos um meio de gerar excees atravs do Raise. Download do Aplicativo de Teste. (Fonte dos exemplos mostrados aqui no artigo) Para iniciar, vamos relembrar como tratar excees com as clusulas Try, Except e Finally num determinado trecho do cdigo. Nunca construir tratamento de excees dessa forma: Try ... Except ... Finally ... End; Forma correta de tratar excees usando Try, Except, Finally: Try Try ... Except ... End; Finally ... End; Podemos opcionalmente construir: Try Try ... Except ... End; Finally

Try ... Except ... End; ... End; A seguir, apresento a lista das excees que descrevem os tipos bsicos - h centenas de classes da exceo: Classe - Descrio Exception - Exceo genrica, usada apenas como ancestral de todas as outras excees EAbort - Exceo silenciosa, pode ser gerada pelo procedimento Abort e no mostra nenhuma mensagem EAccessViolation - Acesso invlido memria, geralmente ocorre com objetos no inicializados EConvertError - Erro de converso de tipos EDivByZero - Diviso de inteiro por zero EInOutError - Erro de Entrada ou Sada reportado pelo sistema operacional EIntOverFlow - Resultado de um clculo inteiro excedeu o limite EInvalidCast - TypeCast invlido com o operador as EInvalidOp - Operao invlida com nmero de ponto flutuante EOutOfMemory - Memria insuficiente EOverflow - Resultado de um clculo com nmero real excedeu o limite ERangeError - Valor excede o limite do tipo inteiro ao qual foi atribuda EUnderflow - Resultado de um clculo com nmero real menor que a faixa vlida EVariantError - Erro em operao com variant EZeroDivide - Diviso de real por zero EDatabaseError - Erro genrico de banco de dados, geralmente no usado diretamente EDBEngineError - Erro da BDE, descende de EDatabaseError e traz dados que podem identificar o erro Exemplos: 1 - Nesse Exemplo, temos uma ocorrncia normal da Aplicao utilizando Try, Finally -> Try, Except . O cdigo na clusula Try executado por completo e em seguida, o cdigo da clusula Finally executado entrando primeiro na clusula Try que est dentro de Finally, como no gerada nenhuma exceo dentro desse Try o cdigo executado por completo indo em seguida para a ltima linha do Finally.

2 - Nesse Exemplo, temos uma ocorrncia normal da Aplicao utilizando Try -> Try, Except, Finally -> Try, Except. O cdigo na clusula Try -> Try executado por completo e em seguida, o cdigo da clusula Finally executado entrando primeiro na clusula Try que est dentro de Finally, como no gerada nenhuma exceo dentro desse Try o cdigo executado por completo indo em seguida para a ltima linha do Finally.

3 - Nesse Exemplo temos uma ocorrncia de uma diviso por zero na Aplicao utilizando Try -> Try, Except, Finally -> Try, Except. O cdigo na clusula Try -> Try executado at a linha "resultado := dividendo div divisor;", como nessa linha ocorre a exceo "EDivByZero" o cdigo da clusula Except executado verificando o tipo de exceo que foi gerado, repare que nesse exemplo o Except possui apenas 3 tentativas (on EDivByZero do, on EAccessViolation do e else), a tentativa vlida que ser executada on EDivByZero do e aps isso o finally chamado executando o cdigo da mesma forma como mostramos nos exemplos anteriores.

4 - Nesse Exemplo, temos a ocorrncia de um objeto que no criado, ou instancializado se preferir, ser utilizado para atribuio de valor em Try -> Try, Except, Finally -> Try, Except. O cdigo na clusula Try -> Try executado at a linha "MinhaStringList.Text := '1';", como o objeto MinhaStringList no foi criado ("MinhaStringList := TStringList.Create;"), essa linha gera a exceo "EAccessViolation", ento, o cdigo da clsula Except executado verificando o tipo de exceo que foi gerado, executando a

linha on EAccessViolation do e aps isso o finally chamado executando o cdigo da clusula Try que por sua vez tambm gera uma exceo. A exceo ocorre porque tentamos destruir um objeto que no foi Criado, linha "MinhaStringList.Destroy;". Assim o cdigo em Except executado e aps isso o restante do cdigo do finally executado.

5 - Nesse Exemplo, temos uma ocorrncia parcialmente normal da Aplicao utilizando Try -> Try, Except, Finally -> Try, Except. O cdigo na clusula Try -> Try executado por completo e em seguida, o cdigo da clsula Finally executado entrando primeiro na clsula Try que est dentro de Finally, quando a linha "MinhaStringList.Destroy;" executada ocorre uma exceo porque tentamos destruir um objeto que j havia sido destrudo, linha "MinhaStringList.Destroy;" em Try -> Try. Assim o cdigo em Except executado e aps isso o restante do cdigo do finally executado.

6 - Nesse Exemplo, temos uma ocorrncia parcialmente normal da Aplicao utilizando Try, Finally -> Try, Except. O cdigo na clusula Try executado por completo e em seguida, o cdigo da clsula Finally executado entrando primeiro na clsula Try que est dentro de Finally, quando a linha "MinhaStringList.Destroy;" executada ocorre

uma exceo porque tentamos destruir um objeto que j havia sido destrudo, linha "MinhaStringList.Destroy;" em Try. Alm disso estamos forando a finalizao da Aplicao "Application.Terminate;". Assim o cdigo em Except executado e o Raise permite que a Exceo seja exibida ao usurio, ento, a Aplicao nem chega a executar restante do cdigo do em finally. Creio que o Raise pode ser usado de outras formas tambm, esse apenas um exemplo.

7 - Nesse Exemplo, temos uma ocorrncia de uma diviso por zero na Aplicao utilizando Try -> Try, Except, Finally. O cdigo na clusula Try -> Try executado at a linha "resultado := dividendo div divisor;", como nessa linha ocorre a exceo "EDivByZero" o cdigo da clsula Except executado, mas dessa vez, sem verificar o tipo de exceo que foi gerado, porque diferente do exemplo Nmero 3 que possuia 3 tentativas (on EDivByZero do, on EAccessViolation do e else), o exemplo 7 mostra um tratamento genrico, linha ("on E : Exception do"). Dessa forma a Aplicao entende que qualquer exceo ocorrida deve ser tratada pelo cdigo dentro de "on E : Exception do". Essa idia pode ser aplicada a outros tipos de Excees, bastando apenas, voc definir um tratamento genrico a todos os problemas que possam ocorrer.

Existem muitas formas de trabalhar com Tratamento de Excees de forma com que a aplicao fique mais robusta. Um outro exemplo a possibilidade de criarmos nossa prpria exceo. Em type digite: type EUsuarioInvalido = class (Exception); No evento OnClick do boto digite: raise EUsuarioInvalido.Create('Usurio Invlido');

Em execuo:

Excees e o Debbuger Enquanto voc estiver usando o Delphi para testar sua aplicao, ver que antes das mensagens de tratamento de excees serem exibidas uma notificao de Exceo da IDE exibida para voc (passando a impresso de que o tratamento de exceo no funcionou), ento, pressionando a tecla F9 possvel dar continuidade a aplicao. Mas as vezes isso fica sendo chato para testar nossa aplicao. No meu caso acabei testando fora do Delphi rodando o executvel. Para testar a aplicao sem que aparea a notifcao de Exceo da IDE do Delphi faa o seguinte: (Delphi 2006) -> Desmarque a opo Notify on language exceptions , no menu Tools | Options | Debugger Options | Borland Debuggers | Language Exceptions . Dessa forma as mensagens de exceo do depurador no sero mostradas.

Potrebbero piacerti anche