调试是指查找、隔离并解决软件程序中被称为“bug”的编码错误的流程。调试有助于找出编码错误的原因,防止软件功能出现问题,并提高软件的整体性能。
调试通常涉及六个步骤:
- 重现条件
- 查找 bug
- 确定根本原因
- 修复 bug
- 测试以验证修复是否有效
- 记录流程
调试过程要求具体;工程师不能依靠问题的二手描述来准确诊断问题。因此,调试过程的第一步就是重现导致 bug 出现的条件。重现 bug 可以让程序员和工程师第一时间观察到错误,并为调试过程的其余部分收集上下文数据。
下一步是通过彻底检查代码和查看所有可用日志,尽可能准确地找出 bug 来源。在此步骤中,开发人员通常依靠调试工具来更轻松地搜索大量代码,而不是手动工作。
开发人员通过检查代码的逻辑和流程,以及代码的不同组件在出现 bug 的特定条件下是如何交互的,来确定导致 bug 的原因。
此步骤通常包括故障排除和修改代码以纠正问题,以及重新编译和重新运行软件以确保 bug 已修复。此类修订可能涉及多次迭代,因为首次尝试可能会失败或无意中引入新的 bug。
大多数开发人员使用版本控制系统来跟踪更改,这样他们就可以轻松回滚任何未能解决问题或引入了新问题的修改。
错误修复后所运行的测试包括:
最后一步,开发人员记录修复过程的详细信息,包括导致 bug 的原因、修复方式以及任何其他相关信息。对于程序员来说,文档记录是一个宝贵的工具,在将来出现类似 bug 时可以借鉴。
了解系统面临的 bug 类型使软件工程师和开发人员能够在出现错误时找到适当的方法来修复损坏的代码。需要调试的常见错误示例包括:
违反编码语言规则的代码会导致语义错误。与产生错误输出的逻辑错误不同,语义错误不会产生有意义的输出。
当开发人员错过某一代码元素(例如,括号、逗号或其他印刷错误)时,便会出现此错误。与人类书面语言(一个存在印刷错误的句子可能仍可读懂)不同,缺少代码片段会立即导致错误。
此类错误包括学术上正确但方向不正确的语法,从而会导致意外输出。由于该语法正确,这些错误可能很难被检测到。当系统并未立即崩溃时,查找错误代码的实际位置可能十分耗时。
此类错误在应用程序运行或启动时发生。运行时错误偶尔可以通过刷新、重启或重新安装应用程序来修复。其他时候,它们可能是程序需要更多内存或其他类型错误(如逻辑错误)的信号。
调试过程具有挑战性,需要大量人力。了解调试过程的各种方法可以更有效地管理任务。
通过这种方法,开发人员从检测到错误的点开始逆向工作以找到 bug 的根源。具体来说,他们会用有问题的源代码回溯程序所采取的步骤,以查看哪里出了问题。与调试器一起使用时,回溯会非常有效。
基于假设的调试技术“原因排除法”要求团队推测错误的原因,并单独测试每种可能性。当团队熟悉代码和 bug 周围的情况时,此方法效果最佳。
在调试大型代码库时,团队可以将代码行分成几段(函数、模块、类方法或其他可测试的逻辑部分),然后分别测试每个部分以找出错误。确定问题段后,可以对其进行进一步划分和测试,直到确定 bug 的来源。
打印和日志调试策略包括在代码中添加打印语句或“日志”以显示变量的值,调用堆栈,执行流程和其他相关信息。这种方法对于调试并发或分布式系统特别有用,因为在这些系统中,执行顺序会影响程序的行为。
在这种方法中,开发人员会向任何无生命的对象逐行“解释或讲述”代码。其理念是,通过大声解释代码,开发人员可以更好地理解其逻辑(或发现缺乏逻辑)并更容易发现 bug。
蛮力调试通常在其他方法失败时部署,需要逐行检查整个代码库以确定问题的根源。当执行调试的工程师或程序员不熟悉代码库时,这种耗时的方法也可用于调试小程序。
独立调试器(例如 GNU Debugger (GDB))提供高级调试功能,包括条件断点和观察点。它们还有助于反向调试,即程序员反向运行程序。它们往往比 IDE 或其他开发人员工具内置的调试器更强大、功能更丰富,但用户的学习曲线也更陡峭,需要更多技术专业知识。
这些工具提供了在代码的各个点记录程序状态的方法。然后可以分析日志以发现异常或有问题的模式。日志记录对于解决生产环境中发生的 bug 很有用,因为在生产环境中,交互式调试可能不可行。
静态代码分析工具无需运行代码即可进行分析,寻找潜在错误并修复 bug 和偏离编码标准的情况。这些工具并不像解释器和编译器那样关注语法,而是分析源代码的语义,帮助开发人员检测常见的编程错误并强制执行一致的编码风格。
动态分析工具本质上与静态代码分析器相反,它是在软件运行时对其进行监控,以检测资源泄漏或并发问题等问题。此工具可帮助开发团队捕获静态分析可能遗漏的 bug,例如内存泄漏或缓冲区溢出。
性能剖析器可帮助开发人员找出代码中的性能瓶颈。此类系统可以测量 CPU 使用率、内存使用率和 IO 操作,帮助找出缓慢和低效的操作。
测试和调试是新代码开发中的互补过程。虽然结果不同,但测试和调试都是为了生成无差错的代码。
测试使软件开发人员能够了解出现 bug 时系统会发生什么。这些测试可帮助开发人员了解系统何时发生故障,以及该故障可能对软件产生的影响。自动化测试使开发人员能够对新代码进行持续测试,以深入了解各种场景。测试是软件开发的关键部分,但它不能解释错误发生的原因。
开发人员使用调试策略和工具来查找错误的根本原因、修复错误并记录下来以防止错误再次发生。当一起使用时,调试和测试可帮助团队构建一种简化的方法来开发代码和创建更好的软件产品。
完全托管的单租户服务,用于开发和交付 Java 应用程序。
使用开发运维软件和工具,在多种设备和环境中构建、部署和管理云原生应用程序。
云应用程序开发意味着一次构建、快速迭代和随处部署。
1 “全球软件调试市场分析 [2023-2030]”,Benzinga,2022 年 9 月 5 日
2 “Google 的 Bard AI 聊天机器人已可生成并调试代码”,TechCrunch+,2023 年 4 月 12 日
3 “自主调试视频游戏”。南加州大学维特比工程学院,2023 年 4 月 5 日
4 “从编程语言中消除错误的一种更简方法”,MIT News,2023 年 4 月 7 日