为什么在IDE中debugging更好?

我从事软件开发已有二十多年,使用C,Perl,SQL,Java,PHP,JavaScript和最近的Python进行编程。 我从来没有遇到过一个问题,我不能仔细考虑debugging和print语句。

我尊重很多人说我的技术是原始的,在IDE中使用真正的debugging器要好得多。 然而从我的观察来看,使用我的石刀和熊皮,IDE用户似乎没有比我更快或更成功的debugging。 我真诚地开放,学习正确的工具,我从来没有显示出使用可​​视化debugging器的强大优势。

此外,我从来没有阅读过如何使用IDE进行有效debugging的教程或书籍,超出了如何设置断点和显示variables内容的基础知识。

我错过了什么? 什么使得IDEdebugging工具比周到地使用诊断print语句更有效?

你能build议显示IDEdebugging更精细技术的资源(教程,书籍,屏幕录像)吗?


甜蜜的回答! 非常感谢大家花时间。 非常照亮。 我投了很多票,没有投下任何票。

一些值得注意的地方:

  • debugging器可以帮助我对variables,代码或运行时环境的任何其他方面进行临时检查或更改,而手动debugging则需要我停止,编辑和重新执行应用程序(可能需要重新编译)。
  • debugging器可以附加到正在运行的进程或使用崩溃转储,而通过手动debugging,“重现”缺陷的步骤是必需的。
  • debugging器可以以更易读的方式轻松显示复杂的数据结构,multithreading环境或完整的运行时栈。
  • debugging器提供了许多方法来减less时间和重复性的工作来完成几乎所有的debugging任务。
  • 可视debugging器和控制台debugging器都很有用,并具有许多共同的特性。
  • 集成到IDE中的可视化debugging器还使您能够在单个集成开发环境(即名称)中轻松访问智能编辑和IDE的所有其他function。

IDEdebugging器将通过代码跟踪消息的某些function的一些示例:

  • 在任何时候查看调用堆栈 ,为您提供当前堆栈帧的上下文。
  • 进入库 ,你不能重新编译的目的是添加跟踪(假设你有权访问debugging符号)
  • 在程序运行时更改variables值
  • 编辑并继续 – 在运行代码时更改代码的能力,并立即查看更改的结果
  • 能够观察variables,看到变化的时间
  • 能够跳过或重复一段代码 ,看看代码将如何执行。 这使您可以在做出理论修改之前进行testing。
  • 检查内存内容的实时
  • 即使应用程序处理了某些exception ,也会警告您。
  • 有条件的突破 ; 仅在特殊情况下停止应用程序才能分析堆栈和variables。
  • 在multithreading应用程序中查看线程上下文 ,使用跟踪很难实现(因为来自不同线程的跟踪将在输出中交织)。

总之,打印语句(通常)是静态的 ,如果原始语句不够详细,则需要重新编译以获取更多信息。 IDE消除了这个静态屏障,为您提供了一个dynamic的工具包。

当我第一次开始编写代码的时候,我不明白与debugging器有什么大不了的,我想我可以通过跟踪来实现任何事情(理所当然,在unix上,debugging器是GDB)。 但是,一旦你学会了如何正确地使用graphicsdebugging器,你不想回到打印语句。

  • IDEdebugging器允许您在运行时更改variables的值。

  • 一个IDEdebugging器可以让你看到执行开始时你不知道你想看到的variables的值。

  • 一个IDEdebugging器可以让你看到调用堆栈并检查函数传递奇怪值的状态。 (认为​​这个函数是从数百个地方调用的,你不知道这些奇怪的值来自哪里)

  • 一个IDEdebugging器可以让你有条件地在代码中的任何一点中断执行,基于条件而不是行号。

  • 一个IDEdebugging器将让你检查程序的状态,在未处理的exception的情况下,而不是只是出来。

这里有一件事情,你绝对不能用“打印”语句进行debugging,这是当客户给你带来内存转储,并说“你的程序崩溃了,你能告诉我为什么吗?

  • 通过您的代码打印报表降低了可读性。
  • 添加和删​​除它们仅用于debugging目的是非常耗时的
  • debugging器可以跟踪调用堆栈,从而轻松查看您的位置
  • variables可以随时修改
  • 临时执行期间可以执行临时命令来协助诊断
  • 可以在打印语句中使用IN CONJUNCTION:Debug.Write(“…”)

我认为使用打印语句进行debugging是一种失落的艺术,对于每个开发人员来说都是非常重要的。 一旦你知道如何做到这一点,某些类的错误比通过IDE更容易debugging。 知道这种技术的程序员也非常好的感觉到,在日志消息中放入什么有用的信息(更不用说你实际上最终会读取日志了),以便进行非debugging。

也就是说,你真的应该知道如何使用step-throughdebugging器,因为对于一个不同类别的bug,这样做更容易一些。 我会把它留给已经发布的其他优秀的答案来解释为什么:)

closures我的头顶上:

  1. debugging复杂对象 – debugging器允许您深入到对象的内部。 如果你的对象有一个复杂对象数组的数组,那么print语句只会给你一个这样的结果。
  2. 跳过代码的能力 – debugging器也允许你跳过你不想执行的代码。 当然,你也可以手动完成这个工作,但是你必须注入更多的代码。

作为在IDE中进行debugging的替代方法,您可以使用php库来尝试优秀的Google Chrome浏览器扩展PHP控制台 ,

  • 在Chrome浏览器JavaScript控制台和通知popup窗口中查看错误和例外。
  • 转储任何types的variables。
  • 远程执行PHP代码。
  • 通过密码保护访问。
  • 按请求分组控制台日志。
  • 跳转到文本编辑器中的错误文件:行。
  • 将错误/debugging数据复制到剪贴板(对于testing人员)。

我近20年来一直没有开发,但是我发现使用IDE /debugging器我可以:

  • 看到我可能没有想到包括在打印声明中的各种各样的东西
  • 通过代码来查看它是否符合我认为需要的path
  • 将variables设置为某些值以使代码占用某些分支

使用IDE的一个原因可能是现代IDE支持的不仅仅是简单的断点。 例如,Visual Studio提供了以下高级debuggingfunction:

  • 定义条件断点(只有在满足条件的情况下才中断,或者只在断点处的语句执行的第n次)
  • 打破一个未处理的exception,或每当(特定)ecxeption被抛出
  • debugging时更改variables
  • 通过设置要执行的下一行来重复一段代码
  • 等等

另外,使用debugging器时,一旦完成debugging,就不必删除所有的打印语句。

有一件事,我很惊讶,我没有看到在另一个答案是2debugging方法不是相互排斥的

即使使用标准的debugging器(不pipe是否基于IDE), printfdebugging也可以很好地工作。 特别是使用日志框架,因此您可以在发布的产品中保留所有或大部分内容,以帮助诊断客户问题。

正如在这里所提到的所有其他答案中所提到的,标准debugging器的关键之处在于它允许您更轻松地检查(并可能更改)程序状态的细节。 你不必知道你可能想要看什么 – 这一切都可以在你的指尖(或多或less)。

根据我的经验,简单的打印输出有一个似乎没有人提到的巨大优势。

IDEdebugging器的问题是,所有事情都是实时发生的。 您在某个特定时间停止了该程序,然后逐步执行一个步骤,如果您突然想要查看之前发生的事情,则无法返回。 这与我们的大脑如何工作是完全不同的。 大脑收集信息,逐渐形成思维。 这样做可能需要多次迭代事件,但是一旦你跨过某个点,就不能回头了。

与此相反,选定的一系列打印输出/日志logging为您提供了“时间事件的空间投影”。 它给你一个完整的故事发生了什么事情,你可以很容易地往回几次,只需滚动上下。 它可以很容易地回答这样的问题,如“乙发生之前发生了一件事”。 它可以让你看到你甚至寻找的模式。

所以在我的经验。 IDE和debugging器是解决简单问题的绝佳工具,当单个调用堆栈中的某些内容出错时,可以在某个崩溃时探索机器的当前状态。

但是,当我们处理涉及国家逐渐变化的更多的难题时。 例如,一个algorithm破坏了一个数据结构,反过来导致失败algorithm失败。 或者,如果我们想回答诸如“发生这种事情的频率”这样的问题,“按照我想象中的事情发生的顺序,按照顺序发生”。 那么“旧式”的logging/打印技术就有了明显的优势。

最好的方法是在最合适的时候使用这两种技术,例如使用日志/打印输出来解决一些错误,并且在需要更详细地探索当前状态的断点处暂停。

也有混合方法。 例如,当您执行console.log(object)时,您将在日志中获得一个数据结构小部件,您可以对其进行扩展和详细探索。这比“死”文本日志有许多明显的优势。

因为使用print语句debuggingmultithreading应用程序将驱动你的香蕉。 是的,你仍然可以用打印语句来做,但是你需要很多这样的语句,并且从语句中解开连续的打印来模拟multithreading的执行过程需要很长的时间。

人类的大脑不幸的是只有单线程。

这是我最常用的VS.NETdebugging窗口:

  • 调用堆栈,这也是弄清别人代码的好方法
  • 当地人&手表
  • 立即窗口,这基本上是一个C#控制台,也让我改变variables的内容,初始化的东西等
  • 可以跳过一行,设置下一条语句在其他地方执行
  • hover在variables上的能力,并有一个工具提示给我看他们的价值

总之,它使我能够360度地看到执行代码的状态,而不仅仅是一个小窗口。

从来没有find一本教这种东西的书,但是再一次,它似乎很简单,它几乎是所见即所得。

既然你问了书籍的指针……就Windowsdebugging而言,John Robbins有好几本关于Windowsdebugging的书:

为Microsoft .NET和Microsoft Windowsdebugging应用程序

请注意,最新版本( debuggingMicrosoft .NET 2.0应用程序 )仅限于.NET,所以如果您希望本机代码debugging(它涵盖.NET和本机),您可能需要一个较旧的版本(如在第一个链接中)。

我个人觉得答案就像“一个集成的debugging器/ IDE快速地给你提供了大量不同的信息,而不需要在命令中打孔,信息总是在你的面前,而你没有告诉它什么给你看

信息可以被检索到的简单程度,不仅仅是命令行debugging,还是“printf”debugging。

debugging器优于printf( 注意不是IDEdebugging器,而是任何debugging器

  1. 可以设置观察点。 这是我最喜欢的发现内存损坏的方法之一

  2. 可以debugging一个你现在不能重新编译的二进制文件

  3. 可以debugging花费很长时间重新编译的二进制文件

  4. 可以随时更改variables

  5. 可以即时调用函数

  6. 没有debugging状态不刷新的问题,因此计时问题不能被debugging

  7. debugging器帮助核心转储,打印语句不'

  • debugging器可以附加到正在运行的进程

  • 通常更容易从debugging器debugging线程代码

使用IDEdebugging器,无论何时停止执行,您都可以看到当前作用域中所有variables的值(一直调用堆栈)。

打印语句可以很好,但是在任何给定的地方向屏幕倾倒这么多的信息会产生大量的打印语句。

此外,许多IDEdebugging器允许您键入和评估方法,并在停止时评估成员,这进一步增加了您必须执行的打印语句的数量。

我觉得debugging器对于某些语言比对其他语言更好。

我的一般观点是IDEdebugging器对于像Java或C#这样的托pipe语言来说绝对是非常棒的,对于C ++来说是非常有用的,而且对于像Python这样的脚本语言来说并不是非常有用(但是可能是我没有尝试过一个好的debugging器的任何脚本语言呢)。

我非常喜欢IntelliJ IDEA中的debugging器,当我进行Java开发时。 我只使用打印语句,当我使用Python。

正如有人所说:Debugger!= IDE。

gdb和(今天回来)TurboDebugger(独立)工作得很好,因为他们支持的语言,谢谢。 (或更老的技术:连接到xBase可执行文件本身的Clipperdebugging器) – 这些都不需要IDE

另外,尽pipeC / ++编码更为罕见,但是printf语句有时会掩盖您正在尝试查找的错误! (例如,堆栈中的自动variables的初始化问题,或内存分配/alignment)

最后,正如其他人所说,你可以同时使用两者。 一些实时问题几乎需要印刷,或者至less是一个明智的“* video_dbg =(is_good?'+':' – ');” video内存的某处 我的年龄正在显示,这是在DOS下:-)

TMTOWTDI

除了其他海报的大部分内容之外,我真的很喜欢随着计算机一起走过一条线,因为它迫使我一次只考虑一条线。 通常我会在没有查看variables值的情况下捕捉到这个bug,仅仅是因为我点击“下一行”button时我不得不查看它。 不过,我不认为我的答案会帮助你,比尔,因为你可能已经有了这个技能。

至于学习资源去,我没有用过 – 我只是探索所有的菜单和选项。

这真的是真正的程序员的问题吗?

任何人只要用打印语句debugging5分钟,然后用IDEdebugging – 甚至连问都不会问!

我已经使用打印和IDE进行debugging,我宁愿debugging使用IDE。 对于我来说,只有当这种情况不能正常工作的时候,才会出现严重的情况(比如debugging在线游戏),在这些情况下,用打印语句抛弃代码,然后在日志文件发生严重错误之后再查看日志文件。 然后,如果你仍然无法弄清楚,添加更多的打印和重复。

只是想提一下IDE中的控制台debugging器vs printf和vsdebugging器的一个有用的function。

您可以附加到远程应用程序(显然,在DEBUG模式下编译),并检查其状态使用POSIX tee实用工具将debugging器输出转储到文件。 与printf相比,您可以select在运行时输出状态的位置。

在debugging部署在激进环境中的Adobe Flash应用程序时,它帮了我很大的忙。 您只需要定义一些在每个断点处打印所需状态的操作,使用fdb | tee output.log启动控制台debugging器 fdb | tee output.log ,并遍历一些断点。 之后,您可以打印日志并通过彻底比较不同断点中的状态来分析信息。

不幸的是,GUIdebugging器很less提供[logging到文件]function,使开发人员比较头部对象的状态。

顺便说一下,我的意见是,应该在开始debugging之前计划在哪里debugging什么。

那么另一件事是,如果你join一个新的旧项目,没有人真正知道代码是如何做它做的,那么你不能通过回显variables/对象/debugging/ …你不知道代码是什么执行完毕。

在我的工作中,我正面临着这种情况,视觉XDebuging帮助我了解正在发生的事情以及在哪里。

最好的祝福

拉斐尔

除了已经提到的许多事情之外,debugging器相对于printf最重要的优点之一是使用printf语句假定您知道该错误驻留在哪个函数中。 在许多情况下,你不这样做,所以你必须做一些猜测,并将打印语句添加到许多其他function,以便本地化。 这个错误可能在框架代码中,或者远离你认为的地方。 在debugging器中,设置断点来检查代码的不同区域和不同时间点的状态要容易得多。

此外,一个体面的debugging器将允许您通过将条件和操作附加到断点来执行printf样式的debugging,以便仍然保留printfdebugging的优点,但不修改代码。

在错误日志和shell访问不可用的环境(如共享主机)中,在IDE中进行debugging是非常有用的。 在这种情况下,带有远程debugging器的IDE是唯一允许你做简单的事情的工具,比如view stderr或者stdout

使用打印语句的问题是它使你的代码变得混乱。 IE浏览器,你有10个部分的function,你知道它崩溃的地方,但你不知道在哪里。 因此,您可以添加10个额外的打印语句来查明错误的位置。 一旦你find并解决了你的错误,你现在必须清除所有这些打印语句。 也许你会这样做。 也许你会忘记,它会在生产结束,用户的控制台将充满debugging打印。

Wauw,我喜欢这个问题吗? 我从来没有敢于提出…

人们似乎有不同的工作方式。 对我来说最好的是:

  • 有我的代码的坚实的头脑模型,包括内存pipe理
  • 使用工具(如打印语句)来跟踪发生的事情。

我已经赢得了40多年的生活编程,每天在C ++和Python中进行非平凡的技术和科学应用程序工作,而且我有一个debugging器不能帮助我的个人经验。

我不这么说。 我不这么说。 我只是想分享。

It's not just debugging. An IDE helps you build better software faster in a lot of ways:

  • refactoring tools
  • intellisense to make api's more discoverable, or remind of exact spelling/case of familiar items(not much use if you've used the same system for 15 years, but that's rare)
  • save on typing by autocompleting variable and class names
  • find certain kinds of errors before you even start to compile
  • Automatically jump to variable/method/class declarations/definitions, even if they're not in the same file or folder.
  • Break on unhandled and handled exceptions

我可以继续。