排错

维基百科,自由的百科全书
(重定向自除错
跳转到导航 跳转到搜索

排错,又称除错故障排除,是解决问题的一种形式,通过系统化的方法诊断和修复各类系统中的问题,在系统管理电子工程软件工程等领域有广泛应用。排错过程一般要求参与者熟悉系统的正常运行状态及近期的变更历史,并通过排除法将问题一步步简化。

排错涵盖从机械故障诊断到软件缺陷修复的广泛范围。在软件工程领域,排错的特化形式称为调试(debugging),即查找、分析和修复程序错误的过程。[1]对于软件排错,常用的手段包括交互式调试控制流分析、日志文件分析、应用或系统级监控、内存转储分析和性能分析。许多编程语言软件开发工具也提供专门的辅助程序——调试器

词源[编辑]

“troubleshooting”(排错)源于“trouble”(故障)与“shoot”(追踪并消除)的组合。该词最早在20世纪初用于铁路和电话电报行业——当时称为“trouble shooter”的技术工人负责排查通信线路故障。[2]此后该术语逐步扩展到机械、电子和软件等各类系统的故障诊断。

“debugging”(调试)一词中的“bug”用于指代缺陷至少可追溯到1878年,托马斯·爱迪生曾将他的发明中的“小故障和困难”称为“bugs”。[3]

一个广为人知的故事来自1947年的哈佛大学。格蕾丝·霍珀海军少将的团队在哈佛马克二号计算机的一个继电器中发现了一只飞蛾,导致机器故障。团队将这只蛾子贴在日志上,并注明“第一个实际发现bug的案例”。虽然这可能是一个玩笑(将生物bug和缺陷bug的双关含义混为一谈),但这个故事表明该术语在当时已被计算机领域使用。[3]

“debugging”一词在进入计算机领域之前已用于航空工程。1944年10月27日,曼哈顿计划负责人罗伯特·奥本海默在写给欧内斯特·劳伦斯的信中用到了该词。[4]牛津英语词典》收录了1945年一篇航空工程期刊文章中使用“debugging”指代飞机发动机测试的案例。S. Gill于1951年发表的文章是对编程错误的早期深入讨论,但尚未使用“bug”或“debugging”一词。[1]到1963年,CTSS手册第一页已不加说明地使用了“debugging”一词,说明它已成为通用术语。

排错与调试的关系[编辑]

排错(troubleshooting)是一个广义概念,指对任何系统——机械、电子、软件或组织系统——中问题的系统性诊断和修复。调试(debugging)则是排错在软件和电子工程领域的具体应用,聚焦于代码或硬件设计中的缺陷。二者的关系可以概括为:

  • 通用过程相同:无论是排查一台故障发动机还是追踪一个软件崩溃,其逻辑过程是一致的——观察症状 → 形成假设 → 定位根因 → 实施修复 → 验证结果。[1]
  • 领域特定工具不同:机械工程师依赖万用表和示波器,软件工程师依赖调试器和日志分析工具,但底层的排除法和分治法思维是一致的。
  • 调试是排错的特化:软件调试发展出了专门的概念体系(如断点、监视点、核心转储)和技术生态(如静态分析、模糊测试),但这些都属于排错方法论在特定领域中的体现。
  • 反过来说:并非所有排错都是调试。排查网络连接故障、诊断数据库性能瓶颈或修复硬件电路,都属于排错范畴,但一般不称为调试。

过程[编辑]

排错过程通常遵循从观察症状到定位根因的递进路径。通用步骤包括:

  1. 复现问题:确定在什么条件下问题发生。对于软件调试,这可能涉及再现特定的输入或操作序列;对于硬件排错,则可能涉及重现特定的环境条件(温度、负载等)。
  2. 简化范围:通过排除法缩小嫌疑区域——这对应软件调试中的简化测试用例和硬件排错中的分段隔离。
  3. 形成假设:基于系统知识提出可能的原因。
  4. 验证假设:通过实验或进一步观测确认根因。[1]
  5. 修复并验证:实施解决方案并确认问题不再出现。

经典的排错策略之一是分治法,也称作“狼栅算法”。Edward Gauss于1982年如此描述:在阿拉斯加找一只狼,先建一道栅栏把州分成两半,听狼嗥叫确定它在哪一侧,然后重复缩小范围,直到找到为止。[5]在软件版本管理中,Git的`git bisect`命令即利用此算法定位引入缺陷的提交。

对于软件调试,Module:WikidataLink第216行Lua错误:attempt to call field 'entityExists' (a nil value)(由Andreas Zeller提出)是一种自动化简化测试用例的技术,通过系统地排除不相关的输入来缩小故障范围。[6]类似的排除法同样适用于硬件排错——例如逐段检测电路板来隔离短路位置。

技术[编辑]

下列技术主要针对软件调试领域,但在适当类比下也适用于其他类型的排错。

交互式调试[编辑]

利用调试器工具让程序逐步执行,可在任意时刻暂停以检查或修改变量状态。程序员可以设置断点(当执行到特定代码行时暂停)、监视点(当特定变量发生变化时暂停)和捕获点(当发生异常等事件时暂停)。

打印/追踪调试[编辑]

或称printf调试,通过在源代码中插入printf等输出语句来追踪程序执行流程和数据变化。这是最简单也最广泛使用的排错方式。在早期BASIC语言中,TRON(Trace On)命令可开启此功能,程序运行时逐行打印行号。

事后调试[编辑]

在程序崩溃后进行的调试。相关技术包括检查日志文件、输出崩溃时的调用栈信息以及分析崩溃进程的内存转储(或称核心转储)。系统可在进程因未处理异常而终止时自动获取转储,也可由程序员主动触发。[7]

远程调试[编辑]

在不同于调试器所在系统的另一台系统上调试运行中的程序。调试器通过局域网等通信链路连接到远程系统,可以控制远程程序的执行并获取状态信息。

其他技术[编辑]

其他排错技术还包括:记录回放调试(使用Mozilla的rr工具录制程序执行过程,实现可逆调试)、时间旅行调试(在源代码中回溯执行历史)、因果追踪(跟踪计算中的因果关系链)、霰弹调试(漫无目的地修改代码试图修复bug,常引发更多问题)以及自动故障定位(利用机器学习技术识别最可能包含缺陷的程序元素)。[6]

工具[编辑]

排错工具的复杂性从修复简单错误到执行耗时冗长的数据收集和分析不等。调试器是软件工具,使程序员能够监视程序的执行、停止和重启程序、设置断点以及更改内存中的值。

静态代码分析工具(如早期的Unix lint程序)针对源代码中已知的特定问题进行扫描,侧重于语义而非语法。这些工具能检测诸如变量在被赋值前被解引用等问题,但也存在误报率高的问题。对于电子硬件和底层软件(如BIOS设备驱动程序固件)的排错,通常使用示波器逻辑分析仪在线仿真器(ICE)等仪器。

嵌入式系统调试[编辑]

与通用计算机软件不同,嵌入式系统面临平台高度异质性的挑战(不同CPU架构、厂商、操作系统及其变体)。这使得调试和测试更加困难。许多嵌入式处理器内置了片上调试模块(OCDM),通过标准JTAG接口暴露其信号。商业解决方案包括Green Hills Software的SuperTrace Probe和Microchip的MPLAB-ICD(在线调试器)。[8]

反调试[编辑]

反调试是在代码中实施一种或多种技术来阻碍对目标进程的逆向工程或调试。常见手段包括:检查系统信息以探测调试器是否存在、检查异常处理是否被干扰、检测代码修改(调试器设置的软件断点)、检查CPU寄存器和硬件断点、以及通过执行时间延迟检测调试器。反调试技术既被合法软件用于版权保护,也被恶意软件用于逃避检测和分析。[9]

参见[编辑]

参考文献[编辑]

  1. ^ 1.0 1.1 1.2 1.3 Gill, S. The Diagnosis of Mistakes in Programmes on the EDSAC. Proceedings of the Royal Society of London A. 1951, 206 (1087): 538–554. JSTOR 98663. doi:10.1098/rspa.1951.0089 (English). 
  2. ^ Troubleshoot. Merriam Webster Online. [2026-05-26] (English). 
  3. ^ 3.0 3.1 InfoWorld: 33. 1981-10-05 [2026-05-25] (English). 
  4. ^ Letter from J. Robert Oppenheimer to Dr. Ernest Lawrence. 1944-10-27 [2026-05-25]. (原始内容存档于2019-11-21) (English). 
  5. ^ Gauss, E. J. Pracniques: The 'Wolf Fence' Algorithm for Debugging. Communications of the ACM. 1982, 25 (11): 780. doi:10.1145/358690.358695可免费查阅 (English). 
  6. ^ 6.0 6.1 Zeller, Andreas. Why Programs Fail: A Guide to Systematic Debugging. Morgan Kaufmann. 2005. ISBN 1-55860-866-4 (English). 
  7. ^ Postmortem Debugging. Dr. Dobb's. [2026-05-25]. (原始内容存档于2019-12-17) (English). 
  8. ^ SuperTrace Probe hardware debugger. Green Hills Software. [2026-05-25]. (原始内容存档于2017-12-01) (English). 
  9. ^ Shields, Tyler. Anti-Debugging Series – Part I. Veracode. 2008-12-02 [2026-05-25]. (原始内容存档于2016-10-19) (English).