3

我有一些德尔福代码,有点像这样:

try
  //some code
  //occasionally throws an exception here, for example an EIndexOutOfRangeException
  //more code...should get skipped if exception is thrown
finally
  // there may or may not be any important cleanup code here
end;

在这种情况下,除了打破 try 块之外,不需要处理的异常。因此,在将 mad-except 添加到项目以进行错误故障排除之前,此代码是“工作”的。但是现在我收到了错误报告,因为 MadExcept 正在报告未捕获的异常。

相关问题,MadExcept 在 try 上触发最终表明 MadExcept 在这种情况下中断的行为是“预期的”,因为该异常没有“处理”。

我想澄清一下我的选项是什么,以防止在此代码运行时弹出疯狂的异常对话框,无论是否有内部异常被抛出和忽略。

所以我认为没有开关来禁用 MadExcept 以阻止在 try/finally 块中的未处理异常是正确的?即使我想忽略它,我也需要明确地“捕捉”异常?

我应该做这样的事情(忽略任何例外):

try
  //some code
  //sometimes throws EIndexOutOfRangeException here
  //more code...should get skipped if exception is thrown
except do begin end;
end;

或者也许(忽略一个非常具体的例外):

try
  //some code
  //sometimes throws EIndexOutOfRangeException here
  //more code...should get skipped if exception is thrown
except on E : EIndexOutOfRangeException do begin end;
end;

或者可能需要:

try
  try
    //some code
    //sometimes throws EIndexOutOfRangeException here
    //more code...should get skipped if exception is thrown
  except on E : EIndexOutOfRangeException do begin end;
finally
  // some cleanup code
end;

如果所有这三个都是有效的解决方案,我是否应该出于任何原因更喜欢其中一个?

4

2 回答 2

5

所以我认为没有开关来禁用 MadExcept 以阻止在 try/finally 块中的未处理异常是正确的?

是的。 try/finally不是异常处理;保证清理,无论是否发生异常。因此,try/finally块与 MadExcept 等异常处理工具完全无关。

即使我想忽略它,我也需要明确地“捕获”异常?

是的。这就是异常的工作方式。它们沿着堆栈向下工作,直到找到捕获它们的处理程序。如果不存在这样的处理程序,则操作系统将其解释为崩溃并终止程序。Delphi 的TApplication对象在非常靠近调用堆栈的底部安装了一个处理程序,这样您的程序就不会崩溃,而 MadExcept 将其挂钩,以便如果异常到达这一点,将生成一个报告。

如果你想忽略一个异常,是的,你确实需要捕获它,因为你正在做的是正式的“通过在堆栈展开并忽略它的这一点上捕获它来处理异常”。关于“在堆栈展开时捕获它”的部分很重要,因为这意味着堆栈展开在该点停止并且程序恢复正常执行。如果您只是忽略它,(即,在您的代码中没有做任何事情,包括不安装异常处理程序),它将继续展开堆栈一直到默认处理程序,无论您是否安装了 MadExcept。

所以是的,在这种情况下,示例#2 是正确的做法。如果此时需要执行清理代码,示例 #3 也是有效的。但是示例 #1在任何情况下都不应执行,因为这意味着您最终可能会忽略您没有预料到的异常,然后您的程序最终会损坏并且您永远不会意识到它。

于 2014-07-08T23:58:57.640 回答
2

在我看来,您对什么finally意思有一个根本的误解。

finally块不影响异常的传播。它只是确保finally块将执行,即使引发了异常,或者正常的执行流程已被 修改exitbreak等等。

取出 try/finally,madExcept 仍然会报告程序引发了未处理的异常。

有一些方法可以告诉 madExcept 忽略某些异常。例如,一些例外应该是沉默的。典型的例子是EAbort. 您将使用RegisterExceptionHandler自定义未处理异常的处理方式。虽然,正如我将解释的那样,我怀疑这是否是您问题的解决方案。

接下来你需要做的是忘记 madExcept。您需要弄清楚如何处理此异常。你想在这里处理,还是需要让异常传播?只有你才能真正知道。但 madExcept 不是这里的驱动程序。必须推动您做出决定的是正确执行您的程序。是否应该处理异常以使您的程序正常运行?你必须先做对,然后再担心 madExcept。

如果需要在这里处理,那就选择性处理。不要捕获所有异常。这是绝对不行的。但如果你在这里处理它,问问自己这是否明智。代码未能执行某些操作。是否有一些后续代码依赖于该操作的成功?通过处理错误并按照您的建议忽略它,您将迫使所有后续代码对该操作的成功或失败感到矛盾。这对我来说似乎很可疑。

现在,例外是EIndexOutOfRangeException. 这意味着你写了一些类似于A[i]valuei无效的东西。我想不出一个可以接受的场景。因此,在我看来,您的程序包含错误并且只是使用了无效索引。您应该通过不越界访问来正确修复该错误。不要抑制异常,停止引发异常。

另一种看待这个的方式。您如何区分您当前的情况与写作A[-i]而不是写作的情况之间的区别A[i]?抑制异常意味着您无法检测到这样的严重错误。

据我所知,最重要的是 madExcept 报告了您的代码中的错误。你应该把 madExcept 当作你的朋友,听它说什么。它告诉您您的代码中存在应该修复的缺陷。

于 2014-07-09T01:38:13.583 回答