调试是软件开发过程中不可避免的一部分,它可能令人困惑,有时甚至令人烦恼,但对于任何非平凡的程序来说都是必不可少的。近年来,调试工具的进步使得许多调试任务变得更加容易和节省时间。本文总结了十个调试技巧,这些技巧在使用Visual Studio时可以为节省大量时间。
调试可能会很具有挑战性。通过一个函数来理解哪里出了问题,查看调用堆栈以了解某个值的来源……在这两种情况下,添加监视表达式或查看本地变量列表可能需要相当长的时间。然而,如果只是将鼠标指向感兴趣的变量,事情就会变得容易得多。此外,类和结构体可以通过一次点击展开,允许快速方便地找到所需的字段。
调试器不仅仅是分析崩溃和奇怪行为的工具。许多错误可以通过逐步执行新编写的函数并检查其行为是否符合预期来预防。有时,可能会好奇“如果这个条件为真,函数是否会正确行为?”。在大多数情况下,这并不意味着需要更改代码并重新启动。只需将鼠标悬停在变量上,双击值并输入新的值即可!
一个典型的调试场景是通过逐步执行函数来分析为什么函数调用失败。当发现一个函数调用了另一个返回错误的函数时,会怎么做?重新启动调试?有一个更好的主意:只需将黄色语句标记拖动到想要执行的下一行,就像刚刚失败的函数一样,然后简单地步入。简单,不是吗?
调试复杂程序或插件?发现了一个错误,但不想浪费时间停止、重建和重新启动,而函数调用太频繁,无法每次都使用上一个技巧?没问题,只需在原地修复错误并继续逐步执行。Visual Studio将修改程序并继续调试,无需重新启动。
不过,需要注意的是,编辑并继续有一些已知的限制。首先,它不适用于64位代码。如果它拒绝为C#应用程序工作,请转到项目设置,然后选择“x86”作为平台目标。不用担心,发布配置的平台目标与调试配置是分开的,仍然可以是“任何CPU”。
其次,编辑并继续的更改应该是局部的,即在一个方法内。如果更改了方法签名、添加了新的方法或类,将不得不重新启动应用程序,或者撤销更改以继续。更改包含lambda表达式的方法意味着修改自动生成的委托类,因此会阻止继续。
可能每个现代调试器都有一个监视窗口。然而,Visual Studio的真正酷之处在于可以多么容易地在那里添加和删除变量。只需点击空行,输入表达式并按Enter。或者简单地按删除按钮来移除不再需要的表达式。
此外,可以从监视窗口获取的信息不仅限于“正常”变量。可以输入$handles来跟踪应用程序打开的句柄数量(并更容易地找到泄漏),$err来查看最后一个函数的错误代码(然后使用Tools->Error Lookup来获取有意义的描述),或者@eax(对于64位代码是@rax)来查看包含函数返回值的寄存器。
使用交互式汇编模式可以更容易地优化程序关键部分的性能。Visual Studio向展示了与代码每一行对应的指令,并允许逐步运行代码,以及在任意位置设置断点。当然,表达式评估和修改将像C++代码一样工作。
调试多线程应用程序可能会很痛苦。或者它可以很有趣。这取决于调试器。Visual Studio2010的一个非常酷的功能是线程窗口中的堆栈视图。可以方便地查看所有线程,并直接从窗口导航它们的调用堆栈。
如果试图重现一个罕见的事件,并在断点上得到太多误报,可以很容易地使它们有条件!只需为断点指定条件,Visual Studio将自动在条件不成立时忽略断点。
一些错误是由不正确的结构定义、缺少对齐属性等引起的。查看原始内存内容可以简化定位和修复这些错误。Visual Studio提供了一个方便的内存窗口,可以解释为8/16/32/64位数字,以及浮点数字,并允许通过简单地在旧值上输入新值来即时更改它们,就像在文本编辑器中一样。
最后要提到的功能与调试没有直接关系,而是与探索大型项目有关。如果试图在自己没有编写的代码中找到一个错误,快速回答“这个类型是什么”或“这个函数做什么”可以节省很多时间。Visual Studio通过“转到定义”命令轻松实现这一点。