Atenção: por essa edição ser muito antiga não há arquivo PDF para download. Os artigos dessa edição estão disponíveis somente através do formato HTML.
Tratando Erros com Exceções Parte I – Manipulando Exceções
Quando um erro ocorre em seu aplicativo, durante a execução, a aplicação chama uma exceção. Uma exceção é um objeto que contém informações sobre o erro ocorrido e onde ele ocorreu. Se você não especificar em seu código uma resposta ao erro, o Delphi mostrará uma mensagem descrevendo o erro.
O ideal seria que você pudesse tratar os erros ocorridos, evitando a perda de dados ou a necessidade de encerrar a aplicação. Além de tratar o erro a rotina de tratamento de erros poderia enviar ao usuário uma mensagem em português, mais significativa.
Obs: Quando você está no ambiente do Delphi, executa a aplicação e ocorre um erro, o Delphi lhe mostra uma mensagem de erro própria (independente da que você cria para manipular o erro). Você deve fechar esta caixa de mensagem e clicar um Run, para que a execução da aplicação continue. Só neste momento será mostrada a mensagem criada por você para manipular o erro. Quando você executa a aplicação fora do ambiente do Delphi, só a caixa de mensagem criada por você é mostrada.
Mensagem criada pelo usuário
O Delphi permite que você desenvolva aplicações robustas, ou seja, que tratam os erros ocorridos de forma que os dados não se percam. Para fazer uma aplicação robusta, é necessário que o código reconheça exceções quando elas ocorram, respondendo a elas.
Blocos Protegidos
Você cria uma resposta a uma exceção em um bloco de código, chamado de bloco protegido porque está resguardado de erros que podem parar a aplicação ou perder dados. Um bloco protegido começa com a palavra reservada try e termina com a palavra reservada end. Entre estas palavras você determina os comandos protegidos e a forma de reação a erros.
Quando você define um bloco protegido, especifica respostas a exceções que podem ocorrer dentro deste bloco. Se a exceção ocorrer, o fluxo do programa pula para a resposta definida, e após executá-la, abandona a bloco.
A forma mais simples para responder a uma exceção é garantir que algum código limpo é executado. Este tipo de resposta não corrige o erro, mas garante que sua aplicação não termine de forma instável. Normalmente, usamos este tipo de resposta para garantir a liberação de recursos alocados, mesmo que ocorra um erro. Para isto, usamos a estrutura try...finally...end.
Outra forma de se responder a uma exceção é tratando o erro, ou seja, oferecendo uma resposta específica para um erro específico. Ao tratar o erro destruímos a exceção, permitindo que sua aplicação continue a rodar. Para isto, usamos a estrutura try...except...end.
A Estrutura Try...Finally..End
Seu código precisa garantir que, mesmo ocorrendo um erro, os recursos alocados sejam desalocados. Entre estes recursos estão: arquivos, memória, recursos do Windows, objetos.
Para garantir a desalocação dos recursos, usamos a estrutura abaixo:
{aloca os recursos}
try
{códigos que usam recursos}
finaly
{libera os recursos}
end;
A aplicação sempre executará os comandos inseridos na parte finally do bloco, mesmo que uma exceção ocorra. Quando um erro ocorre no bloco protegido, o programa pula para a parte finally, chamada de código limpo, que é executado. Mesmo que não ocorra um erro, estes comandos são executados.
Exemplo
A aplicação a seguir possui uma caixa de edição e um botão:
Ao entrarmos com o valor 0 na caixa de edição, e clicarmos no botão Calcular, geramos um erro, ao tentarmos dividir 10 por 0. Apesar do erro, o programa libera a memória alocada:
procedure Tform1.
Button1Click(Sender:Tobject);
var
Apointer: Pointer;
a, b: Integer;
begin
a:=StrtoInt(Edit1.Text);
GetMem(Apointer, 1024);
try
b:=(10 div a);
Edit1.Text:=IntToStr(b);
finally
FreeMem(Apointer, 1024);
end;
end;
Exceções da RTL
Quando você escreve código que chama rotinas da biblioteca de run-time (RTL, run-time library), como funções matemáticas ou de manipulação de arquivos, os erros aparecem na forma de exceções. Por padrão, a RTL manda uma mensagem para o usuário, mas você pode tratar estes erros de outra forma.
As exceções geradas pela RTL são definidas na unit SysUtils, e todas descendem da classe Exception, que provê a string que aparece no quadro de mensagem da exceção.
Há diversos tipos de exceções geradas pela RTL, como por exemplo:
n exceções de entrada e saída;
n exceções de memória heap;
n exceções matemática envolvendo inteiros;
n exceções matemáticas envolvendo pontos flutuantes;
n exceções de typecast;
n exceções de conversão;
n exceções de hardware.
Você pode observar estas exceções com mais detalhes através do Object Browser, ativado através do comando View|Browser:
Exceções de Entrada e Saída
Ocorrem quando a RTL tenta acessar arquivos ou dispositivos de entrada e saída.
A unit SysUtils define uma exceção genérica de entrada e saída chamada EinOutError, que contém um atributo chamado ErrorCode que indica o erro ocorrido.
Exceções de Memória Heap
Ocorrem quando você tenta alocar ou acessar memória dinâmica. São definidos dois tipos de exceções: EoutOfMemory (indica que não há memória suficiente), e EinvalidPointer (ponteiro inválido).
Exceções Matemáticas para Inteiros
Ocorrem quando você realiza operações com números inteiros. A unit SysUtils define uma exceção genérica chamada EintError, com três tipos de exceções derivadas: EdividByZero (divisão por zero), ErangeError (número ou expressão fora da região), e EintOverflow (estouro na operação com inteiro).
Exceções de Pontos Flutuantes
Ocorrem quando são feitas operações com dados do tipo real. A unit SysUtils define uma exceção genérica chamada EmathError, com as seguintes exceções derivadas: EinvalidOp (procesador encontrou uma instrução indefinida), EzeroDivide (divisão por zero), Eoverflow, Eunderflow.
Exceções de Typecast
Ocorrem quando você tenta atribuir um objeto a um tipo inválido usando o operador as. Gera-se a exceção EinvalidCast quando isto ocorre.
Exceções de Conversão
Ocorrem quando se convertem dados de tipo para outro. A unit SysUtils define uma exceção chamada EconvertError quando isto ocorre, avisando que a conversão não pode ser feita.
Exceções de Hardware
Podem ocorrer em dois tipos de situação: quando o processador detecta uma falha, ou quando a aplicação gera uma interrupção intencional
Entre as exceções de hardware geradas temos: EaccessViolation (acesso ilegal de memória), EstackedOverflow (acesso ilegal ao seguimento stack do processador).
A Estrutura Try..Except..End
Um tratamento de exceção é um código que trata erros que ocorrem dentro de blocos protegidos.
Para definir um tratamento de exceção, utilize a seguinte construção:
try
{comandos que você deseja proteger}
except
{comandos de tratamento}
end;
A aplicação irá executar os comandos na parte except somente se ocorrer um erro. Se na parte try você chamar uma rotina que não trata erros, e um erro ocorrer, ao voltar para este bloco a parte except será executada. Uma vez que a aplicação localiza um tratamento para a exceção ocorrida, os comandos são executados, e o objeto exceção é destruído. A execução continua até o fim do bloco.
Dentro da parte except definimos um código a ser executado para manipular tipos específicos de exceção:
try
{comandos que você deseja proteger}
except
on Exceção do {código a ser executado de acordo com a exceção gerada}
end;
A palavra reservada on define respostas para uma exceção. On está sempre junto de do, para manipular a exceção.
Exemplo
A aplicação apresenta duas caixas de edição e um botão. Ao entrarmos com um número na primeira caixa de edição, este deve ser convertido para inteiro, e mostrando na segunda caixa.
Veja o código do botão Converter:
procedure Tform1.
Button1Click(Sender:tObject);
procedure TForm1.Button1Click(Sender: TObject);
var
a: Integer;
begin
try
a:=StrtoInt(Edit1.Text);
Edit2.Text:=IntToStr(a)
except
on EconvertError do
Edit2.Text := '0';
end;
end;
Quando, ao executarmos a aplicação, inserimos na primeira caixa de edição o valor de 10,5 um erro é gerado, já que 10,5 não pode ser convertido para inteiro. Este erro é da classe EconvertError. Tratamos este erro, ao colocar na segunda caixa de edição o valor 0, quando o erro ocorre.