#tocadoelfo: Sua Aplicação Cairá ... Mas irá se recuperar ... (Pt.:2)
Falando um pouco mais sobre Map Files, um map file detalhado contém, entre outras coisas, uma lista dos endereços de erro e suas respectivas linhas no código fonte, agrupadas para cada arquivo de código fonte que faz parte da aplicação. Como exemplo, algumas linhas de um arquivo .map:
9 0001:001F 10 0001:005B 11 0001:006B 12 0001:0083
Eu tinha encontrado um código que faz exatamente o mesmo que o Search\Erros faz, até descobrir aquele diálogo. Posto aqui o código pra quem se interessar.
if (NewVal > MinV) and (NewVal <= OffValue) then begin LastFileName := FileName; MinV := NewVal; MinL := Line; SourceLine.Caption := Format('Somewhere between %d and %d',[MinL,MaxL]) end else if (NewVal < MaxV) and (NewVal >= OffValue) then
Continuando com a explicação, quando uma violação de acesso em tempo de execução acontece, o usuário recebe um erro parecido com este:
Se sua aplicação foi compilada com informações de depuração, você pode localizar a linha do código correspondente ao código compilado que gerou a violação de acesso.
Uma das causas mais comuns de erros de violação de acesso no Delphi é o uso de um objeto que ainda não foi criado.Se o segundo endereço for FFFFFFF (ou 0000000), com certeza você está tentando acessar um objeto que ainda não foi criado. Por exemplo, chamar um método em um form que não está setado como auto-create e não está instanciado via código.
var AVForm: TAVForm;
//Isto irá gerar um AV
AVForm.Refresh;
Suponha que AVForm esteja listado na lista "Avaliable Forms" na janela Project\Options - forms que necessitam ser criados e destruídos manualmente. No código acima, a chamada ao método Refresh do form AVForm irá causar a violação de acesso.
Se a opção "Stop on Delphi Exceptions" em Debbuger Options\Language Exceptions estiver setada então a mensagem a seguir irá aparecer:
A mensagem mostra que uma exceção EAccessViolation foi lançada. A exceção EAccessViolation é a classe de exceções para erros ligados a acessos inválidos à memória. Esta mensagem aparece quando você está desenvolvendo sua aplicação. a próxima mensagem será vista pelo usuário e, logo em seguida, a aplicação morrerá:
O primeiro número (0043F193) é o endereço do erro de runtime no código compilado (Project1.exe) onde a violação de acesso ocorreu. Na IDE, escolha o menu "Search\Find Error...", entre com o endereço do erro no diálogo e clique em Ok. O Delphi irá recompilar o projeto e mostrará a linha do código fonte onde o erro ocorreu, que no nosso caso, foi em AVForm.Refresh.
Dando prosseguimento ao post, segue uma lista das causas de violação de acesso mais comuns no desenvolvimento em Delphi. Esta lista não é definitiva e, em nenhum momento, tem como objetivo tentar cobrir todas as situações que levam a erros de violação de acesso. Na vida real, estes erros são mais obscuros e de maior dificuldade de detecção.
"O Fantasma da Máquina" - Chamando um objeto inexistente
Como foi dito anteriormente, a grande maioria dos erros de violação de acesso em tempo de execução são relacionados a objetos que não foram criados ou que já foram destruídos. Para prevenir este tipo de erro, devemos nos certificar que todos os objetos que você está usando já foram criados pelo menos uma vez. Por exemplo, abrir uma tabela no evento OnCreate de um form quando o componente TTable está localizado em um data-module que ainda não foi criado (foi removido da lista "auto-create forms").
No exemplo abaixo, um erro de violação de acesso ocorrerá após chamar um método do objeto (b:TBitmap) que já foi destruído.
//faz alguma operação com b
//Esta linha irá causar uma violação de acesso - o objeto b não existe mais
b.Canvas.TextOut(0,0,'this is an Access Violation');
"Ahn ?? Como ??" - Parâmetros Inválidos em APIs
Se você tenta passar um parâmetro inválido para alguma API do sistema (na verdade, qualquer método externo à aplicação), um erro de violação de acesso ocorrerá. A melhor maneira de resolver este problema é consultar a documentação da API do sistema ou dos módulos utilizados e fornecer os tipos esperados pelo método. Por exemplo, tenha sempre o cuidado de não passar um ponteiro inválido em um parâmetro do tipo buffer.
"I believe I can fly" - Deixe o Delphi finalizar seus métodos
Quando um objeto pertence a outro, deixe que o segundo finalize o primeiro. Por exemplo, todos os forms (criados automaticamente), por padrão, são pertencentes ao objeto Application (Owning). Então, quando a aplicação terminar, ela irá finalizar o objeto Application que, em seguida, irá finalizar todos os forms. Por exemplo, se você tem dois forms (Form1/Unit1 e Form2/Unit2), ambos criados automaticamente pela aplicação, o próximo código irá gerar uma violação de acesso:
Form2.ShowModal; //bum!!
"Die another Day" - Matando a Exceção
NUNCA destrua o objeto temporário de exceção (E). Tratar a exceção automaticamente destróis o objeto E. Se você destrói o objeto, a aplicação tentará destruir o mesmo e, novamente, gerará uma violação de acesso.
E.free. // causes an access violation
"I see Dead People" - Acessando posições de uma string vazia
Uma string vazia não contém nenhum dado válido. No entanto, tentar acessar um determinado membro da string vazi é como tentar acessar uma variável Nil e o resultado será, impreterivelmente, uma violação de acesso.
s[1]:='a'; //AV
"Ei, isto é meu seu imbecil" - Referência de Ponteiros
Quando trabalhando com ponteiros diretamente, você precisa tomar o cuidado de sempre trabalhar com a informação armazenada na memória e não com o indicador da mesma. Se você, de alguma forma, alterar o "referencial" do ponteiro, ele possivelmente irá corromper outros locais da memória.
{Esta linha poderá causar uma violação}
{esta está correta}
Bem, isto é tudo no momento. Espero que com estas dicas tanto programadores quanto usuários possam aprender um pouco mais sobre como as aplicações "caem", mas agora também sabem como elas podem se levantar.
Até breve! Que os bons ventos os guiem e as sendas os levem ao seu destino!!
P.S.: Nossa, que frase horrível que eu inventei. Depois dessa, vou parar de tentar ser um bardo ahuaahuahauha