Debugging 有目的地调试而不使用调试器?
以书面形式: 作为个人选择,除了获取堆栈跟踪或一两个变量的值之外,我们倾向于不使用调试器 虽然我没有关于这个主题的经验数据,但我怀疑很多程序员可能“生活”在调试器中,而他们的环境中有一个调试器。但我也怀疑,有许多高效的程序员,比如Kernighan和Pike,避免将调试器作为第一道防线,而是依赖于其他技术 因此,我想问stackoverflow社区: 如果您是那种将称为“调试器”的工具视为最后手段(而不是获取初始堆栈跟踪)的程序员,那么您首先使用其他技术的原因是什么? 请为每个答案提供一(1)个投票理由Debugging 有目的地调试而不使用调试器?,debugging,Debugging,以书面形式: 作为个人选择,除了获取堆栈跟踪或一两个变量的值之外,我们倾向于不使用调试器 虽然我没有关于这个主题的经验数据,但我怀疑很多程序员可能“生活”在调试器中,而他们的环境中有一个调试器。但我也怀疑,有许多高效的程序员,比如Kernighan和Pike,避免将调试器作为第一道防线,而是依赖于其他技术 因此,我想问stackoverflow社区: 如果您是那种将称为“调试器”的工具视为最后手段(而不是获取初始堆栈跟踪)的程序员,那么您首先使用其他技术的原因是什么? 请为每个答案提供一(1)个
我还建议使用以下规则回答:“我不知道如何使用调试器”不是有效的答案。那只是无知。在做出选择之前,你应该了解你的选择 我更喜欢使用TDD并添加一个破坏代码的测试。然后就可以很容易地看到错误发生的地方,并且在没有调试器的情况下修复它。现在我有了一个测试,可以防止该错误 不同的工作需要不同的工具。正如您不会对所有问题都使用Perl一样,您也不会对每个bug都使用调试器。有时使用调试器可以解决问题,有时则不能
以我们的一款产品中出现的bug为例。它是在打印方法之后将最后一个窗口调回焦点。在附加调试器时无法重新生成,但在附加调试器时可以重新生成。这个问题最终用老式的
Console.Write()语句解决了 对于一个普通的愚蠢的小错误来说,在我的脑海中反复阅读代码2到3次调试要比启动调试器并使程序进入所需状态快。我更喜欢手动跟踪代码并观察调试器的日志。调试器把我变成了一个被动的观察者,让我更难看到整个画面
程序执行至少有一个时间轴,在多线程环境中通常不止一个。了解当前执行行之前的几个步骤以及之后会发生什么有助于我跟踪错误。某些错误可能仅在发布模式下显示,因此使用调试器可能不可行。在这些情况下,我经常使用printf:)。这些人来自unix时代,那时还没有成熟的IDE。这就是为什么添加printf要比启动GDB快得多
现在,在VisualStudio中设置断点是调试的最快方法,所以每个人都使用它
在不同的平台(如嵌入式设备)上,将printfs添加到日志文件或类似文件仍然是最快的选择使用调试器作为最后手段的原因是什么
因为,通常情况下,我可以通过使用其他技术比使用调试器更快地找到bug。我们的软件运行在Linux/Solaris/HPUX/AIX/FreeBSD/MacOS上,而且似乎很难为其中一些平台找到调试器,只需添加一些额外的跟踪代码就更容易了。当我有一个可复制的场景时,我肯定会使用调试器来跟踪该bug。
否则,它基本上只用于从核心转储获取堆栈跟踪
跟踪是开始处理问题的基础
铌
车载嵌入式应用程序。我认为Kernighan是在试图强调心理分析。在不了解森林的情况下,不要潜入树林。也就是说,除了调试器之外,还有其他原因让你更喜欢不同的工具,作为你思维的助手
我最喜欢的(如果这是正确的话)例子是内存错误。在C语言或C++语言中,滥用内存系统(双删除,通过死点访问对象,运行数组的末尾)会破坏程序,使问题在原始原因附近没有显现出来。
在这些语言中,适当的方法是使用消除这些错误的实践,但如果做不到这一点,工具也是有价值的。当我遇到类似的bug时,我怀疑“这感觉像是一个内存错误”,在我想到“调试器”之前,我就伸手去拿它
现在我们可以开始讨论自动内存工具和边界检查库是调试器!;^)~ 不使用调试器的两个原因包括:
- 发生故障的客户计算机上未安装调试器
- 您不能停止(客户计算机上的)进程以使用调试器对其进行检查
我不知道我是否是“那种程序员”,但我看不出除此之外你还需要什么样的调试器:
- 在断点处中断和/或在引发异常时中断
- 在中断期间检查数据并检查调用堆栈
我听一些人建议在编写代码时使用调试器逐步检查代码,作为一种代码检查,但我不这样做。在我看来,必须使用调试器可能是一个更深层次问题的迹象
在启动调试器之前,我会问一些针对更深层次问题的问题,比如:
- 哪个测试失败了?如果答案是“没有测试”,那么没有测试故障条件是一个需要首先解决的更深层次的问题
- 异常有哪些信息?(假设环境中存在异常)。如果答案是“没有异常”,或者异常没有太多上下文,那么首先要解决的更深层次的问题是扫描异常被吞没的地方,或者向异常添加更多上下文
- 构建为该部分生成了哪些警告