MadExcept + try / finally阻止?

时间:2014-07-08 23:31:20

标签: delphi madexcept

我有一些delphi代码,有点像这样:

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 triggers on try finally表示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;

如果所有这三个都是有效的解决方案,我是否应该因为某种原因而优先选择其中一个?

2 个答案:

答案 0 :(得分:5)

  

所以我认为没有开关禁止MadExcept打破try / finally块中的无法处理的异常?

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

  

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

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

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

所以是的,在这种情况下,示例#2是正确的行动方案。示例#3也是有效的,如果你有需要在此时执行的清理代码。但是示例#1 绝不应该在任何情况下完成 ,因为这意味着您可能最终会忽略您期待的异常,然后你最终在你的程序中腐败,你永远不会意识到它。

答案 1 :(得分:2)

在我看来,你对finally的含义有一个基本的误解。

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

将try / finally输出,madExcept仍然会报告该程序引发了一个未处理的异常。

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

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

如果您需要在此处理,请选择性地处理它。不要抓住所有例外。这绝对是禁忌。但如果你在这里处理它,问问自己这是否合理。代码无法执行某些操作。是否有一些后续代码依赖于该操作成功?通过处理错误并按照您的建议忽略它,您迫使所有后续代码对此操作的成功或失败产生矛盾。这对我来说似乎非常可疑。

现在,例外是EIndexOutOfRangeException。这意味着您编写了类似A[i]的内容,其中i的值无效。我想不出那种可以接受的情况。因此,在我看来,您的程序包含错误,并且只是使用无效索引。您应该通过不访问越界来正确修复该错误。不要压制异常,停止它被引发。

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

据我所知,底线是madExcept报告代码中的错误。您应该将madExcept视为您的朋友,并听取它所说的内容。它告诉您,您的代码中存在应该修复的缺陷。