异常处理

时间:2008-12-09 14:31:08

标签: .net exception-handling

结构化异常处理是否错误?处理异常的正确方法是什么?

编辑:使用C#在.NET中进行异常处理。

我通常有一组特定的异常类(DivideByZeroException,ArrayTypeMismatchException),并且没有通用的“catch(Exception ex)”。

这背后的想法是,我希望发生某些类型的异常,并在它们发生时定义特定的动作,并且意外的异常会在界面(windows或web)上升。这是一个好习惯吗?

5 个答案:

答案 0 :(得分:6)

我不确定'结构化异常处理'是什么意思。

在异常处理中可以做的最糟糕的事情是“吞下”异常或静默处理它。

不要这样做:

try {
   ...
}
catch (Exception e) {
   //TODO: handle this later
}

这通常是出于懒惰而无法编译代码。如果您不知道如何在特定级别处理异常,请让该方法抛出异常并至少在顶部有一个catch all handler。以某种方式提供反馈(通过GUI,页面/电子邮件发送给支持人员,日志文件),以便最终解决问题。无声地捕获异常几乎总会导致更大的问题在以后发生并且难以追踪。

答案 1 :(得分:3)

Catch语句+堆栈跟踪。在没有打印堆栈跟踪的情况下不要捕获异常,您或其他人必须再次检出该代码,并在发生错误并且日志文件为空或模糊时将堆栈跟踪放在Catch块中。

答案 2 :(得分:1)

我的建议:

除非:

,否则不要捕捉异常
  • 如果不这样做会导致应用程序崩溃(例如在事件处理程序中)
    • 在这种情况下,请务必记录异常,以便您知道发生了什么以及何时
  • 您可以尝试并尝试解决问题(例如,在调用偶尔抛出异常的外部API时实现重试机制(请注意,异常处理不应用于控制程序流))
    • 在这种情况下,只捕获您希望被抛出的特定异常类型

以最高级别捕获异常意味着您获得了最大调用堆栈,这在您查看日志并尝试查看哪些初始操作触发导致异常的事件序列时非常有用。第一名。

答案 3 :(得分:1)

这是一个复杂的主题......有关于此的书......但是...有两种主要类型的异常处理...内联,其中处理潜在错误的代码与代码一致方法或例程将“正常”执行,并且结构化异常处理,其中代码在其他地方,并且基础结构被设计为在发生意外事件(错误)时自动变为异常处理代码...两者都具有优势和不利因素。 “内联”方法往往会产生更混乱(带有错误代码)并且更难以阅读和维护的代码。但由于不需要任何前期分析,因此更容易预先生成。当使用内联错误处理时,您经常会看到返回布尔值或数字“错误”代码的方法,无论metjhod还是例程成功,都会向调用者进行调用。这消除了使例程“返回”有意义的业务值或对象的“功能”语法,(因为按惯例的每个函数都必须返回错误代码)当使用结构化异常处理时,这个问题没有实际意义。

结构化异常处理,otoh,一般来说难以做好,因为它需要事先分析一个例程或方法可能产生的错误,以及该方法可以或应该对每个错误做什么,如果它确实发生了。

有一点可以肯定,不要将这两种方法混合在一个组件中......

答案 4 :(得分:0)

我不是Windows程序员,但在我看来,使用结构化异常处理来处理硬件异常,例如软件异常意味着:

  • 您的代码在C ++标准中执行某些操作(例如除以零)。
  • Windows定义在启用SEH的情况下,它会抛出异常。
  • 您正在使用此事实来捕获异常和/或执行终止处理程序。

所以要问的问题,IMO,是:

  • 您的编程任务是否真的是标准C ++无法处理的? (或者只能通过允许硬件例外以一种明显不如你所获得的方式处理。)
  • 当您的代码不符合标准时,您真的需要采取行动吗?
  • 您是否可以编写代码,以免首先引发硬件异常?

如果答案为“是”,“是”,“否”,则需要进行结构化异常处理。否则你可以避免它,在这种情况下你可能想要。编写异常安全的代码很棘手,因此异常越强,您就可以提供更好的代码。可能用SEH除以零的代码不提供nothrow保证,当可能进行一些重新设计以便呼叫者不给它duff数据时,它可以这样做。但是如果一个函数已经因为其他原因而必须抛出异常,那么也可能将它们抛出硬件陷阱可能会使事情变得更糟。

一个值得注意的特殊情况是内存分配。不确定.NET是否这样做,但是在Linux分配时,如果分配的虚拟地址空间不足,则只会失败。物理内存在首次使用时提交,如果数量不足则会导致硬件异常。由于内存分配假设在失败时抛出std :: bad_alloc,并且实现无法实现标准的这一要求,可能可能在某些情况下转换硬件软件例外是正确的做法。但是,硬件异常可能发生在意想不到的地方(包括你认为没有的例程),所以可能仍然无法正常处理,这就是为什么linux core转储而不是抛出。在实践中,任何完全初始化的东西都会使其构造函数崩溃,这通常足够接近分配,而软件异常则会很有用。