Pergunta

Existe uma boa maneira de descobrir quais exceções um procedimento/função pode gerar no Delphi (incluindo os chamados procedimentos/funções)?

Em Java você sempre tem que declarar quais exceções podem ser lançadas, mas este não é o caso no Delphi, o que poderia levar a exceções não tratadas.

Existem ferramentas de análise de código que detectam exceções não tratadas?

Foi útil?

Solução

(Editar:É agora óbvio que a questão submetida apenas para verificação em tempo de design.)

Nova resposta:

Não posso afirmar se existem ferramentas para verificar isso para você.O Pascal Analyzer, por exemplo, não.

EU pode Digo-lhe, entretanto, que na maioria das aplicações Delphi, mesmo que houvesse uma ferramenta para verificar isso para você, você não obteria resultados.

Por que? Porque o loop de mensagem principal em TApplication.Run() agrupa todas as chamadas HandleMessage() em um bloco de tratamento de exceções, que captura todos os tipos de exceção.Assim, você terá tratamento de exceções implícitas/padrão em torno de 99,999% do código na maioria dos aplicativos.E na maioria dos aplicativos, esse tratamento de exceções será em torno de 100% do seu próprio código - os 0,001% do código que não está envolvido no tratamento de exceções será o código gerado automaticamente.

Se houvesse uma ferramenta disponível para verificar isso para você, você precisaria reescrever Application.run() de forma que não incluísse o tratamento de exceções.

(Resposta anterior:O manipulador de eventos Application.OnException pode ser atribuído para capturar todas as exceções que não são tratadas por outros manipuladores de exceção.Embora este seja o tempo de execução e, portanto, talvez não seja exatamente o que você procura (parece que você deseja identificá-los em tempo de design), ele permite capturar qualquer exceção não tratada em outro lugar.Em conjunto com ferramentas como o material JCLDebug no Biblioteca de Código Jedi, você poderia registrar um rastreamento de pilha para descobrir onde e por que ocorreu uma exceção, o que permitiria uma investigação mais aprofundada e adicionaria tratamento ou prevenção de exceção específica em torno do código culpado...)

Outras dicas

Meu palpite é que você está tentando fazer o Delphi se comportar como o Java, o que não é uma boa abordagem.Aconselho não se preocupar muito com exceções não tratadas.Na pior das hipóteses, eles chegarão ao manipulador de exceção VCL genérico e causarão uma caixa de diálogo de mensagem do Windows.Em um aplicativo normal, eles não interromperão o aplicativo.

Um código bem escrito documentaria as diferentes exceções que podem ser levantadas para que você possa tratá-las de maneira significativa.Manipuladores pega-tudo não são recomendados, pois não há realmente nenhuma maneira de saber o que fazer se você não souber por que uma exceção foi gerada.Também posso recomendar fortemente o madExcept.

Exceto por uma varredura na palavra-chave "raise", não há nenhuma construção de linguagem no Delphi que informe ao leitor casual quais exceções podem ser esperadas de um método.

Em tempo de execução, pode-se adicionar um manipulador de exceção abrangente em cada método, mas isso não é aconselhável, pois diminuirá a velocidade de execução.(E é complicado de fazer também).

Adicionar um bloco de tratamento de exceções a um método adicionará algumas instruções assembly a ele (mesmo quando a exceção não for acionada), o que gera uma desaceleração mensurável quando o método é chamado com muita frequência.

Existem algumas bibliotecas que podem ajudá-lo a analisar exceções de tempo de execução, como loucoExceto, JclDebug, e EurekaLog.Essas ferramentas podem registrar todos os tipos de detalhes sobre a exceção, é altamente recomendável usar uma delas!

A resposta curta é que não existe uma ferramenta que faça o que você diz, e até mesmo uma varredura para o elevação palavra-chave não levaria você até lá. EAcessViolação ou EOutOfMemory são apenas duas de uma série de exceções que podem surgir em qualquer lugar.

Uma coisa fundamental sobre Delphi é que as exceções são hierárquicas:Todas as exceções de linguagem definidas descendem de Exceção, embora seja importante notar que é realmente possível levantar qualquer TObject descendente.

Se você quiser pegar toda exceção levantada em um procedimento específico, basta envolvê-la em um tentar / exceto bloco, mas como foi mencionado isso não é recomendado.

// Other code . . . 
try
  SomeProcedure()
except  // BAD IDEA!
  ShowMessage('I caught them all!');
end;

Isso capturará tudo, até mesmo instâncias de aumento TObject.Embora eu diria que este raramente é o melhor curso de ação.Geralmente você quer usar um tentar / finalmente bloquear e então permitir seu manipulador de exceção global (ou um final tentar / exceto bloco) para realmente lidar com as exceções.

Eu vou em segundo (ou é terceiro) MadExceto.Tenho usado com sucesso em diversas aplicações comerciais sem problemas.O bom do MadExcept é que ele irá gerar um relatório para você com um rastreamento completo da pilha que geralmente apontará a direção certa sobre o que deu errado e pode até incluir uma captura de tela, além de enviá-la automaticamente por e-mail para você do computador do cliente com um simples clique do mouse.

No entanto, você não deseja usar isso para TODAS as exceções, apenas para capturar aquelas que você perdeu.Por exemplo, se você abrir um banco de dados e o login falhar, seria melhor você mesmo capturar e lidar com esse banco de dados, em vez de fornecer ao usuário a mensagem de erro padrão MadExcept na mensagem de ocorrência do seu aplicativo.

Qualquer exceção que não seja explicitamente ou geralmente tratada em um nível específico irá subir na pilha de chamadas.O Delphi RTL (Run Time Library) irá gerar um conjunto de diferentes classes de exceção - (erros matemáticos, erros de acesso, erros específicos de classe etc).Você pode optar por lidar com eles de forma específica ou geral nos diferentes blocos try except.

Você realmente não precisa declarar nenhuma nova classe de exceção, a menos que precise propagar um contexto funcional específico com a exceção.

Como os comentaristas anteriores escreveram, você também pode adicionar a mãe de todos os manipuladores de exceções, como MadExcept ou EurekaLog, para capturar os não capturados.

editar:Este é um seguro geral contra exceções não tratadas

try
  ThisFunctionMayFail;
except
  // but it sure won't crash the application
  on e:exception
  do begin
    // something sensible to handle the error 
    // or perhaps log and/or display the the generic e.description message
  end
end;

Para tempo de execução, tente Eurecálogo.Não sei se existe uma ferramenta para tempo de design.Você terá mais dificuldades mesmo quando tiver código de terceiros sem fonte.Não há necessidade no Delphi de capturar exceções, portanto você não precisa declará-las como em Java.

O que eu queria dizer é que o Delphi não exige que uma exceção seja tratada.Isso apenas encerrará o programa.EurekaLog fornece meios para registrar exceções tratadas e não tratadas e fornece uma riqueza de informações sobre o estado do programa quando a exceção ocorreu, incluindo a linha de código em que ocorreu e a pilha de chamadas no momento.

Como salienta Jim McKeeth, não se pode obter uma resposta definitiva, mas parece-me que se poderia parcialmente responda à pergunta por meio de alguma análise estática:dada uma função/procedimento específico, construa um gráfico de chamadas.Verifique cada uma das funções nesse gráfico de chamada para obter uma instrução raise.Isso lhe diria, por exemplo, que TIdTcpClient.ReadString pode gerar um EIdNotConnected (entre outros).

Um analisador inteligente também pode notar que algum código usa o operador / e inclui EDivByZero como uma possibilidade, ou que algum procedimento acessa um array e inclui ERangeError.

Essa resposta é um pouco mais restrita do que simplesmente pedir "aumentar".

As seções de finalização das unidades também podem gerar exceções.Estes vão passar despercebidos, eu acho...e também são um tanto problemáticos.

Acho que o Delphi IDE tem um "rastreamento de pilha" ou "árvore de pilha" integrado, algo parecido.

Esta pergunta me lembra o jogo T RussianRoulette do Skybuck...pesquise no Google, o código e a resposta podem ajudar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top