.NET的Visual Studio调试器提示和技巧


70

我已经使用VS的调试器进行了多年的工作,但是时不时地遇到一个从未见过的功能,然后想:“该死!我怎么会错过呢?它是如此有用!”

[免责声明:这些技巧可在VS 2005中用于C#项目,不能保证VS或其他语言的较早版本。]

跟踪对象实例

使用给定类的多个实例?你怎么区分他们?在垃圾收集前编程的日子里,跟踪引用很容易-只需查看内存地址即可。使用.NET,您无法做到这一点-对象可以随意移动。幸运的是,手表视图使您可以右键单击手表,然后选择“制作对象ID”。

手表查看http://img403.imageshack.us/img403/461/52518188cq3.jpg

这会在实例的值之后附加一个{1#},{2#}等,从而有效地为该实例提供了唯一的标签。看起来像这样:

编号实例http://img383.imageshack.us/img383/7351/11732685bl8.jpg

标签在该对象的生存期内一直存在。

监视变量的有意义的值

默认情况下,监视变量的值是它的类型。如果要查看其字段,则必须对其进行扩展,如果有很多字段或它们做了复杂的事情,这可能会花费很长时间(甚至是超时!)。

但是,某些预定义类型显示了更有意义的信息:

  • 字符串显示其实际内容
  • 列表和字典显示其元素数量等。

有意义的信息http://img205.imageshack.us/img205/4808/37220487md1.jpg

为我自己的类型拥有它不是很好吗?

嗯...

...使用.NET Reflector的一些优质时间表明DebuggerDisplay,使用我的自定义类型上的属性可以轻松完成此操作:

[System.Diagnostics.DebuggerDisplay("Employee: '{Name}'")]
public class Employee {
    public string Name { get { ... } }
    ...
}

...重新运行,然后...

da!http://img60.imageshack.us/img60/926/79816018ha1.jpg

这里有关于此主题的更多信息:MSDN

打破所有例外

...甚至是用代码处理的!我知道,自从我出生以来就一直不知道这件事,我真是个n00b,但是无论如何,这还是有可能的-也许这有一天会帮助某个人:

您可以在每次引发异常时强制已调试的进程进入调试模式。曾经进行过数小时的错误查找,只是遇到了这样的一段代码吗?

try {
    runStrangeContraption();
} catch(Exception ex) {
    /* TODO: Will handle this error later */
}

在这些情况下,捕获所有异常非常方便。可以从Debug> Exceptions ...(Ctrl-Alt-E)启用。选中“引发”列中需要的每种异常类型的框。


那对我来说是一些拍额的时刻。你愿意分享你的吗?


这不是问题,更像是对自己的笔记,但也许其他人会发现它很有用。希望我也能学到一些新东西。
Cristian Diaconescu

Answers:


7

两个代码技巧:

我真的很喜欢System.Diagnostics.DebuggerStepThrough属性;您可以将其附加到类,方法或属性上,以使VS在调试时默认不输入代码。我比DebuggerHidden属性更喜欢它,因为如果您确实需要调试它,它仍然允许您将断点放在忽略的代码中。

另一个(有时)有用的调用是System.Diagnostics.Debugger.Launch() ; 当执行成功时,将显示“选择调试器”对话框,然后将启动调试器。有点粗鲁,但特别讨厌将其附加到进程,例如被另一个派生并立即执行您的代码的进程。


2
我最近了解了System.Diagnostics.DebuggerStepThrough-有用。另外,碰巧我在过去的两周中频繁使用了Debugger.Launch-对于一个特定的项目,如果我尝试直接从“附加到进程”对话框中进行附加,则进程会死掉,但使用Debugger.Launch ()附加(相同?!)调试器就可以了。
Cristian Diaconescu

19
try {
    // do something big
}
catch {
    // breakpoint set here:
    throw CantHappenException("something horrible happened that should never happen.");
}

您如何看待最初引发的异常?在监视窗口中,输入$ exception


1
真?甜!这太有用了。特别是当您编写的项目不佳时。
2011年

17

这是我学到的另一个巧妙技巧:

System.Diagnostics.Debugger.Break()

以编程方式导致调试器在下一条指令上中断。在真正好的部分,这也适用于在编译的程序发布模式,无需调试信息。


7
我更喜欢用If(System.Diagnostics.Debugger.IsAttached){System.Diagnostics.Debugger.Break()}包围它,否则,如果不删除客户端,客户端可能会收到讨厌的错误!
加文·米勒




6

.load sos 在立即窗口中:)


1
有什么解释?互联网上有无数页面解释如何使用SOS。
嬉皮

4

工具->附加到流程-容易忘记,但是有了它,我可以调试网页中的脚本,在另一个流程中加载的托管代码(认为是加载项模型),甚至是非托管代码。让它自动选择您感兴趣的调试类型时要小心。

跟踪点(以及其他断点功能...右键单击断点并享受乐趣)!-- http://blogs.msdn.com/saraford/archive/2008/06/13/did-you-know-you-can-use-tracepoints-to-log-printf-or-console-writeline-info-without -编辑您的代码237.aspx

即时窗口很棒。

远程调试如果您部署应用程序(并且可以到达可以重现问题的计算机),则非常有用。

还有更多。尝试进入WinDbg和SoS!


不幸的是,我刚刚了解到这些不适用于Express版。
Michael Haren

4

我发现“模块”窗口非常有用。它告知调试器是否已加载所需的dll,以及该dll的版本。它还允许您手动加载或卸载dll。


3

如果您有很多重复的代码,但仅在特定条件下失败,则条件中断非常有用,例如循环中的代码,循环中调用的方法或多个线程中调用的方法。将break语句放在目标行,并设置其条件以匹配错误情况。(这里有一个简单的例子在这里。)


2

来自我的两句话:我希望每个人都在整个地方使用它:

Debug.Assert(<condition>, <message>)

第二个DebuggerHidden:

<DebuggerHidden()> _
Public Sub ReadDocumentProperty(ByVal propertyName As String, ByRef PropVal As Integer, ByVal DefaultVal As Integer)
    Try
        Dim prop As Office.DocumentProperty
        prop = CustomProps.Item(propertyName)
        PropVal = CType(prop.Value, Integer)
    Catch
        PropVal = DefaultVal
    End Try
End Sub

即使设置了“调试”,“异常”,“抛出异常时中断”,也不会捕获此处的异常。


1

创建一个宏以附加到进程并分配给未使用的键盘快捷键。快得多:调试->附加到进程->在进程列表中搜索该进程-> ...


2
Ctrl-Sh-P表示“附加到处理”。您仍然必须搜寻进程名称,但...
Cristian Diaconescu 2010年

1

将IDE设置为在发生异常时也可以分成异常,即使我们没有设置任何调试点也如何。

调试->异常->通用语言运行时异常->抛出

这使查找隐藏的异常处理问题变得轻而易举。实际上,这是每个开发人员都应在整个开发过程中进行的设置,以避免发生任何未处理甚至处理过的异常。


非常有用,但是依赖于“正常”代码流的异常的开发人员可能会破坏它。在我从事的大型项目中,有很多异常只是在程序初始化时被“随意”抛出和捕获。我通常会启动该过程,等待它初始化,然后才启用“抛出异常中断”。
Cristian Diaconescu

0

在非托管代码中,您可以设置“数据断点”。他们使用CPU的调试寄存器来发出INT3,并且调试器在运行期间在没有任何开销的情况下停止该指令(在旧版本中,调试器逐步执行程序检查内存......慢!)

如果您在knwon地址上有一些损坏(堆栈/堆可变区被破坏),这将很有用。

ide \ packages \ debugger中的AutoExp.dat也可以自定义以显示您的数据结构。

指针,mb在监视窗口中显示一个十六进制转储 http://msdn.microsoft.com/zh-cn/magazine/dd252945.aspx

好吃

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.