有没有一个好方法来找出Delphi中过程/函数可以引发哪些异常(包括它称为过程/函数)?

在 Java 中,您始终必须声明可以引发哪些异常,但在 Delphi 中并非如此,这可能会导致未处理的异常。

是否有任何代码分析工具可以检测未处理的异常?

有帮助吗?

解决方案

(编辑:现在很明显,这个问题提到了 仅有的 设计时检查。)

新答案:

我无法说明是否有任何工具可以为您检查这一点。帕斯卡分析器就是其中之一,它不具备这种能力。

然而,告诉您,在大多数 Delphi 应用程序中,即使有工具可以为您检查这一点,您也不会得到任何结果。

为什么? 因为 TApplication.Run() 中的主消息循环将所有 HandleMessage() 调用包装在异常处理块中,该块捕获所有异常类型。因此,在大多数应用程序中,大约 99.999% 的代码都将具有隐式/默认异常处理。在大多数应用程序中,此异常处理将是您自己的代码的 100% 左右 - 未包含在异常处理中的 0.001% 的代码将是自动生成的代码。

如果有一个工具可以为您检查这一点,您将需要重写 Application.run() 以使其不包含异常处理。

(之前的回答:可以指定 Application.OnException 事件处理程序来捕获其他异常处理程序未处理的所有异常。虽然这是运行时,因此可能不完全是您所追求的(听起来您想在设计时识别它们),但它确实允许您捕获任何其他地方未处理的异常。与 JCLDebug 等工具结合使用 绝地代码库, ,您可以记录堆栈跟踪以找出异常发生的位置和原因,这将允许进一​​步调查并围绕有罪代码添加特定的异常处理或预防...)

其他提示

我的猜测是你试图让 Delphi 表现得像 Java,这不是一个好方法。我建议不要太担心未处理的异常。在最坏的情况下,它们将冒泡到通用 VCL 异常处理程序并导致 Windows 消息对话框。在正常的应用程序中,他们不会停止应用程序。

编写良好的代码将记录可能引发的不同异常,以便您可以以有意义的方式处理它们。不建议使用包罗万象的处理程序,因为如果您不知道引发异常的原因,则实际上无法知道该怎么做。我也强烈推荐 madExcept。

除了对“raise”关键字的扫描之外,Delphi 中没有任何语言结构可以告诉普通读者某个方法可能会出现哪些异常。

在运行时,可以在每个方法中添加一个捕获所有异常的处理程序,但这并不可取,因为它会减慢执行速度。(而且做起来也很麻烦)。

向方法添加异常处理块会向其中添加一些汇编指令(即使未触发异常),这会在频繁调用该方法时形成可测量的减慢速度。

确实存在一些库可以帮助您分析运行时异常,例如 疯狂的例外, Jcl调试, , 和 尤里卡日志. 。这些工具可以记录有关异常的各种详细信息,强烈建议使用其中之一!

简短的回答是没有任何工具可以执行您所说的操作,甚至扫描 增加 关键字不会让你到达那里。 电子访问违规 或者 E内存不足 这只是几乎任何地方都可能引发的众多异常中的两个。

Delphi 的一个基本特点是异常是分层的:所有定义的语言异常都源自 例外, ,尽管值得注意的是,实际上可以提高任何 对象 后裔。

如果你想 抓住 在特定过程中引发的每个异常,只需将其包装在 尝试/除外 块,但正如前面提到的 不推荐这样做.

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

这将捕获所有内容,甚至是引发的实例 对象. 。尽管我认为这很少是最好的行动方案。通常你想使用 尝试/最后 阻止然后允许您的全局异常处理程序(或最后一个 尝试/除外 块)来实际处理异常。

我会第二(或者是第三) 疯狂例外. 。我已经在几个商业应用程序中成功使用它,没有任何问题。MadExcept 的好处在于,它会为您生成一份包含完整堆栈跟踪的报告,该报告通常会为您指出出现问题的正确方向,甚至可以包含屏幕截图,并且会自动通过电子邮件发送给您只需单击鼠标即可从客户端计算机。

但是,您不想将其用于所有异常,只是为了捕获您错过的异常。例如,如果您打开一个数据库并且登录失败,您最好自己捕获并处理这个问题,而不是在您的应用程序中向用户提供 MadExcept 默认错误消息。

任何未在特定级别显式或一般处理的异常都将在调用堆栈中向上流动。Delphi RTL(运行时库)将生成一组不同的异常类 -(数学错误、访问错误、类特定错误等)。您可以选择在不同的 try except 块中专门或一般地处理它们。

您实际上不需要声明任何新的异常类,除非您需要使用异常传播特定的功能上下文。

正如之前的评论者所写,您还可以添加所有异常处理程序的母亲,例如 MadExcept 或 EurekaLog 来捕获未捕获的异常。

编辑:这是针对未处理异常的全面保险

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;

对于运行时尝试 尤里卡洛格. 。我不知道是否存在设计时的工具。即使您有没有源代码的第三方代码,您也会遇到更多困难。Delphi 中不需要捕获异常,因此您不必像 Java 中那样声明它们。

我想说的是Delphi并不要求处理异常。它只会终止程序。EurekaLog 提供了记录已处理和未处理异常的方法,并提供有关异常发生时程序状态的大量信息,包括发生异常的代码行和当时的调用堆栈。

正如吉姆·麦基斯(Jim McKeeth)指出的那样,你无法得到明确的答案,但在我看来,人们可以 部分地 通过一些静态分析回答问题:给定一个特定的函数/过程,构建一个调用图。检查该调用图中的每个函数是否有 raise 语句。例如,这会告诉您 TIdTcpClient.ReadString 可以引发 EIdNotConnected (等等)。

聪明的分析器还可能注意到某些代码使用 / 运算符并可能包含 EDivByZero,或者某些过程访问数组并包含 ErangeError。

这个答案比简单地寻找“加注”要严格一些。

单元的最终确定部分也可能引发异常。我想这些都会过去……并且也有些问题。

我认为 Delphi IDE 有一个内置的“堆栈跟踪”或“堆栈树”之类的东西。

这个问题让我想起了 Skybuck 的 TRussianRoulette 游戏……谷歌一下,它的代码和答案可能会有所帮助。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top