通过Visiual Studio调试理解异常

如果您花了任何时间编写代码,很可能您不得不处理异常处理。在Visual Studio中,当异常被抛出或最终未被处理时,调试器可以帮助您通过中断来调试这些异常,就像在遇到断点时中断一样。下面我们将讨论异常的不同分类,以及如何配置调试器何时为这些异常中断。

异常分类

我们将从调试器中异常的分类类型开始。调试器按以下方式对异常进行分类:

First Chance Exceptions:

当应用程序中首次抛出异常时,这被归类为“First Chance”异常。此时,调试器不知道应用程序是否会捕获(处理)异常。所有异常都以第一次机会异常开始。

  • 每次引发异常时都会通知调试器。您可以在输出窗口和IntelliTrace中看到这些通知。
  • 您可以告诉调试器要中断的首次机会异常,就像启用断点一样。
  • 一旦由于首次出现异常而中断,可以通过单步执行或按“继续”继续调试。当您继续时,您的代码有机会处理此异常,如果没有,则该异常现在属于下面列出的分类之一。

User-unhandled Exceptions:

当用户代码中没有捕获(处理)第一次机会异常,并且在调用堆栈的“外部代码”中捕获时,这被归类为“用户未处理”异常。此分类仅适用于仅启用我的代码调试托管或JavaScript应用程序时。

  • 默认情况下,调试器将为所有用户未处理的异常而中断。
  • 一旦由于用户未处理的异常而中断,可以通过单步执行或按“继续”继续调试。异常可以在调用堆栈的“外部代码”中的某个位置处理,如果不是,则它将成为未处理的异常。
  • 您可以更改默认设置,但在大多数情况下,您可能不需要更改此设置。大多数框架,比如ASP.NET,都实现了全局异常处理程序,这样应用程序就不会崩溃,但是异常并没有得到正确的处理。调试器为用户未处理的异常提供中断功能,以便在这些情况下通知您。

Unhandled Exceptions:

当应用程序未捕获(处理)第一次机会异常并到达系统默认处理程序时,这被归类为“未处理”异常。
  • 未处理的异常将使应用程序崩溃。
  • 调试器将中断所有未处理的异常,以便您有机会检查导致崩溃的应用程序的状态。
  • 一旦由于完全未处理的异常而中断,则无法继续调试。

配置调试器First Chance中断

要更改调试器何时中断,请转到“调试”->“窗口”->“异常设置”

当您第一次打开这个窗口时,您将看到有一个树状网格,其中有一列和复选框。

  • Break When Throw,这包括调试器已知的默认异常列表,按类别分组。
    注意:可能从此列表中中断的异常由正在调试的运行时确定。例如,如果您使用的是仅托管调试,则调试程序将永远不会中断C++、Win32异常等,即使它们在配置时被配置为在抛出时中断。
  • 复选框。如果选中某个类别的复选框,则调试器将在调试时为所有第一次机会异常而中断。如果您不想启用所有第一次机会异常,则可以使用搜索框找到要配置的特定异常类型。

使用上下文菜单,可以显示“附加操作”列,还可以为用户未处理的异常配置行为。

  •  Additional Actions.只有启用“仅我的代码”时,此列才可用。用户未处理的异常仅对公共语言运行时异常和JavaScript运行时异常有意义,为其他运行时配置此异常的选项不可用,因为调试器不区分用户代码和外部代码。根据我之前的评论,您通常不想关闭此功能。如果确实要关闭此功能,可以从上下文菜单中选择“在用户代码中未处理时继续”。

此列表不是所有可能异常的详尽主列表。可以使用“添加”和“删除”来管理此默认列表中的异常。此配置随解决方案一起保存。您还可以使用search来查找具有特定关键字的所有异常,例如“null”。最后,可以使用“全部重置”将列表还原为其默认状态。

例子

在本例中,我们使用一个简单的WPF应用程序,当用户单击按钮时,该应用程序将在窗口中绘制形状。这个应用程序已经实现,当出现问题时在视图中显示“Failure”文本,当一切正常时显示“Success”。
让我们假设我得到了这个应用程序来测试并确保一切正常。
  • 我开始调试(F5)以运行应用程序。
  • 点击“绘制半八角形”。
  • 注意故障信息。

应用程序没有崩溃,调试器也没有中断,但我看到了应用程序的失败消息,没有半八角形,所以发生了什么?我可以从输出窗口或IntelliTrace开始调查。让我从输出窗口开始,在文章的最后,我将用IntelliTrace诊断这个问题。
提示:当您认为有问题时,输出窗口和IntelliTrace是很好的起点。

在输出窗口中,我看到“发生了'System.NullReferenceException'类型的第一次机会异常…”如果我再次按“Draw Half octgon”,我就看不到更多的第一次机会异常发生,因此我断定此异常发生在启动路径上。

但具体发生在哪里?

  • 我可以使用代码检查来寻找问题,或者逐步完成初始化逻辑。
  • 相反,我将打开异常设置(Ctrl+Alt+E),并将调试器配置为针对first chance System.NullReference异常中断。

我使用搜索框查找“System.NullReferenceException”。

当抛出此异常类型时,我选中该框以断开。
提示:在“搜索”框中,可以按向下箭头选择列表中的项目,然后使用空格键切换复选框状态。
重新启动调试后,当抛出异常时,调试器会中断,我可以快速验证异常是否由空的catch块“处理”而不是真正处理,这就是导致应用程序中出现“Failure”消息的原因。
提示:如果您不熟悉特定类型的异常,异常助手可以为您提供有用的信息。注意,我也可以从这里通过使用“抛出此异常类型时中断”复选框来配置异常设置。

因为我在第一次机会异常时被打断了,所以我可以转到Locals窗口,在那里我可以看到“m_halfocagon”的值为空。看看代码,我发现变量从未初始化过。

然后我重新启动调试并观察我的应用程序是否成功运行。

原文地址:https://www.cnblogs.com/yilang/p/12856203.html