使用 Visual Studio 调试时了解异常

本文介绍了Visual Studio中异常处理的概念及分类,包括第一次机会异常、用户未处理异常和未处理异常,并详细说明了如何配置调试器中断这些异常的方法。

如果您已花费任何时间进行编码, 则可能是您必须处理异常处理。在 Visual Studio 中, 当异常被抛出或结束时未处理时, 调试器可以帮助您调试这些故障, 就像断点被命中时中断一样。在本博客文章中, 我们将研究异常的不同分类, 以及如何配置调试器何时中断这些异常

例外的分类
我们将首先查看调试器中异常的分类类型。调试器按以下方式对异常进行分类:

第一次机会例外:当第一次在应用程序中引发异常时, 这被归类为 "第一次机会" 异常。此时, 调试器不知道应用程序是否会捕获 (处理) 异常。所有异常都以第一次机会异常开始。
每次引发异常时都会通知调试器。在 "输出" 窗口和IntelliTrace中可以看到这些通知.
您可以告诉调试器要中断的第一个机会例外, 就像启用断点一样。
由于第一次机会异常而中断, 您可以通过步进或按继续来继续调试。在继续时, 您的代码有机会处理此异常, 如果不这样做, 则该异常现在属于下面列出的分类之一。
 用户未处理的异常:当在用户代码中未捕获 (处理) 第一次机会异常并在调用堆栈上的 "外部代码"中捕获时, 这将被归类为 "用户未处理" 的异常。仅当启用了仅我的代码调试托管或 JavaScript 应用程序时, 此分类才适用。
默认情况下, 调试器将中断所有用户未处理的异常。
由于用户未处理的异常而中断, 您可以通过步进或按继续来继续调试。该异常可能在调用堆栈的"外部代码"中的某处进行处理, 如果不是, 则它将成为未处理的异常。
ExternalCode

您可以更改默认值, 但在大多数情况下, 您可能不需要更改此设置。大多数框架 (如 ASP.NET) 都实现全局异常处理程序, 以便您的应用程序不会崩溃, 但该异常并未真正得到正确处理。调试器为用户未处理的异常提供了中断, 以便在这些情况下通知您。
未处理的异常: 当应用程序未捕获 (处理) 第一次机会异常并到达系统默认处理程序时, 这将被归类为 "未处理" 异常。
未处理的异常将使应用程序崩溃。
调试器将中断所有未处理的异常, 以便您有机会检查导致崩溃的应用程序的状态。
由于完全未处理的异常而中断, 因此无法继续调试。
配置调试器以中断第一次机会异常
要在调试器中断时更改, 请转到 "调试" > "窗口-> 例外设置"

当您第一次打开此窗口时, 您将看到有一个带有一列和复选框的树网格。

引发时中断。这包括由调试器已知的默认异常列表, 按类别分组。
注意: 可能从该列表中中断的异常由正在调试的运行时决定。例如, 如果您使用的是仅托管调试, 则调试器将永远不会中断 c++、Win32 异常等, 即使它们被配置为在引发时中断.
复选框。如果选中某个类别的复选框, 则调试时调试器将中断所有第一次机会异常。如果不想启用所有第一次机会异常, 则可以通过使用 "搜索" 框找到要配置的特定异常类型。
使用上下文菜单, 您可以显示 "附加操作" 列, 还可为用户未处理的异常配置行为。

其他操作。仅当启用了 "我的代码" 时, 此列才可用。用户未处理的异常仅对公共语言运行时异常和 JavaScript 运行时异常有意义, 因此, 为其他运行时配置此选项是不可用的, 因为调试器不区分用户代码和外部代码.根据我先前的评论, 您通常不希望关闭此项。如果希望关闭此功能, 可以通过从上下文菜单中选择 "在用户代码中进行未处理时继续" 来完成此操作。
此列表不是每个可能的异常的详尽的主列表。可以使用 "添加和删除" 来管理此默认列表中的异常。此配置与解决方案一起保存。您还可以使用 "搜索" 查找具有特定关键字的所有异常, 例如 "null"。最后, 您可以使用 "全部重置" 将列表还原到默认状态。

例如
对于这个例子, 我们使用一个简单的 WPF 应用程序, 应该在用户单击按钮时在窗口中绘制一个形状。该应用程序已经实现, 以显示 "失败" 文本的看法时, 当事情出错了, "成功" 时, 一切都走错了。您可以跟随附加到此帖子的代码.

让我们假设我被赋予这个应用程序测试, 并确保所有的工作。

我开始调试 (F5) 运行应用程序。
点击 "画半八角形"。
观察失败消息。
AppFailure

该应用程序没有崩溃, 调试器没有中断, 但我看到应用程序的失败消息和没有半八角形形状, 那么发生了什么?我可以先去输出窗口或 IntelliTrace 进行调查。让我从输出窗口开始, 在文章的末尾, 我将诊断 IntelliTrace 的问题。
提示: 输出窗口和 IntelliTrace 是一个伟大的地方开始时, 你认为有什么错了。

在 "输出" 窗口中, 我看到 "类型" 系统的第一次机会例外. 引发发生了... "如果我再次按下 "绘制半八角形", 我看不到任何更多的第一次机会异常发生, 所以我断定此异常发生在启动路径上。

但它到底发生在哪里?

我可以使用代码检查来尝试寻找问题, 或者逐步完成初始化逻辑。
相反, 我将打开异常设置 (Ctrl + Alt + E), 并将调试器配置为第一次机会系统中断. NullReference 异常。
我使用搜索框找到 "系统. 引发"。

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

ExceptionAssistant

由于我在第一次机会例外的情况下被打破, 我可以去当地的窗口, 在那里我可以看到 "m_halfOctagon" 的值为 null。查看代码时, 我看到变量从未初始化。
我添加一行代码来初始化变量。

然后, 我重新启动调试并观察我的应用程序工作成功。

使用 IntelliTrace 诊断同一问题
上面描述的经验适用于所有语言和 Visual Studio 的所有版本/sku。然而, 有些应用程序经常抛出异常, 它们不一定表示失败。在这些情况下, 使用 IntelliTrace 诊断问题的效率要高得多。IntelliTrace 是可用的, 当使用视觉演播室的终极版, 也使用. NET。现在让我告诉你如何使用 IntelliTrace 来发现这个问题。

让我们从第一次观察 UI 中的 "失败" 消息开始。而不是打开 "输出" 窗口并在那里寻找第一次机会异常, 我可以点击工具栏上的 "全部中断" 按钮 ("暂停" 图标), 然后查看诊断工具窗口查看我的调试历史记录。


通过查看 IntelliTrace 事件列表, 我可以看到, 只要我的应用程序启动了一个异常就会被吞下。我要从那里开始。现在, 我选择 "引发:" 事件并激活历史调试。

历史调试将我带到抛出异常的代码行。我再次发现了 null 引用导致我的应用程序失败, 就像以前一样, 但这次是因为我使用了 IntelliTrace 我没有重现问题, 重新启动调试, 或配置异常打破时抛出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值