什么是最好的通用练习调试技巧?不是那些与特定平台,语言等相关联的,而是与您所使用的内容以及使用什么系统无关的内容。
答案 0 :(得分:2)
我首先提供一个我认为非常棒的人:
难以发现的错误通常发生在相对罕见的情况下。毕竟,如果程序在每次运行时重新启动系统,通常会修复该错误。其中一些罕见的情况是由执行以前从未执行过的代码路径引起的。程序首次启动时,通常会创建许多对象。如果那些构造函数抛出异常但是它们曾经失败了,你有一个代码路径吗?
如果没有,你有一个等待发生的事故。当特定构造函数失败时,您的程序实际执行了什么操作?只要您没有测试过代码路径,就没有对程序进行全面测试。确保您运用每个代码路径。如果你有一个“if()... else ...”并且你总是执行“else”部分,那么“if”部分就是等待发生的错误。
有一种非常简单的方法可以解决这个问题,并且可以在首次运行代码时帮助您完成。使用陷阱的好处是它可以立即帮助您,您会很快发现在编写代码时会自动将它们放入。
它由两个方法组成:trap()和trap(bool) - 我已经包含了Java,C ++和&汇编程序示例,但为了说明,我将在这里使用C#。当你遇到一个陷阱时,陷阱会让你进入调试器。首先是这个例子,然后为什么这么有用
// Open an XML file
XmlReader reader;
if (string.IsNullOrEmpty(username)) {
Trap.Trap();
reader = XmlReader.Create(filename, xmlSettings);
} else {
Trap.Trap(!hasDomain);
Trap.Trap(hasDomain);
XmlUrlResolver resolver = new XmlZipResolver();
resolver.Credentials = hasDomain ? new NetworkCredential(user, password, domain) : new NetworkCredential(user, password);
xmlSettings.XmlResolver = resolver;
reader = XmlReader.Create(filename, xmlSettings);
}
即时支付
为什么从一开始就是一个很大的帮助?因为它可以帮助您单步执行代码的每个部分。在上面的代码中,您可能首先测试没有用户名,因此您将陷入第一个陷阱的调试器中。您标记它然后跨步创建。你可以在确定xml好后再单步几行,然后再去。
注意:我标记陷阱的方式是将**放在该行的开头。当我完成一个调试会话时,一个简单的编译将显示我添加* 的每个地方。因为我将* 添加到同一行,所以行号保持不变,并且调试器与源行正确匹配(如果在命中时删除带有陷阱的行,调试器将在任何地方进一步关闭在那个文件中。)
好的,所以你已经在这个模块上工作了几天,它运行良好,你决定尝试一个需要凭据的XML文件。当你这样做时,调试器将停在else的顶部。然后,您将逐步完成使用凭据打开XML文件的代码。这种方法的优点是你不需要记住你没有走过这4行代码。你不需要去找那4行代码。它只是让你在调试器中。 我认为这是我使用的最强大的调试工具之一,因为我现在很容易单步执行代码的每一行 - 并从这种做法中找到足够的问题,使其值得。
次要支付
这种做法也提供了第二次巨大的回报。最初删除的所有陷阱都是非常常见的代码路径或由于单元测试而特别命中的路径。因此,当您使用模块“完成”并且编写了所有测试时,任何剩余的陷阱都是仍需要编写的测试的指示器。您现在可以非常轻松地识别需要编写的剩余单元测试。
并且实现了陷阱,因此它们仅在调试版本上运行。因此,您可以在其中发送带有陷阱的代码(我们不应该,但我们都这样做),它对发布版本没有任何影响。
C#,Java,C ++和& Cp的陷阱代码汇编程序在One of the Most Powerful Debugging Practices
处可用答案 1 :(得分:0)
简单好旧的日志记录是迄今为止最强大的调试技术。如果语言支持条件编译,则可以从发布版本中排除所有日志记录和断言。如果没有 - 你仍然可以在外部使用预处理器。
结构良好的日志记录和全面的断言也可以更好地自我记录您的代码。
如果明智地使用日志记录和断言,则不需要交互式调试器。
答案 2 :(得分:0)
我认为没有一两件事情是最好的,而是你通过经验积累的过程。我个人确保有单元测试,一个很棒的交互式调试器和打印输出。
如果我没有对错误进行单元测试,我会添加一个单元测试,有效地修复错误,然后追踪它。将单元测试放在一起的过程是探索性的,可以帮助您找到导致错误发生的确切环境。