侦错

计算机编程软件开发中,调试是在计算机程序软件系统中查找和解决错误(防止正确操作的缺陷或问题)的过程。

调试策略可以涉及交互式调试,控制流量分析,单位测试集成测试日志文件分析,在应用程序系统级别,内存转储分析。许多编程语言和软件开发工具还提供程序来帮助调试,称为辩论者

词源

Mark II的计算机日志条目,将飞蛾贴在页面上

术语“错误”和“调试”通常归因于1940年代海军上将Grace Hopper 。当她在哈佛大学的一台Mark II计算机上工作时,她的同事发现了一个蛾子陷入接力赛,从而阻碍了操作,于是她说他们正在“调试”该系统。但是,从“技术错误”的意义上说,“错误”一词的历史至少可以追溯到1878年,而托马斯·爱迪生(Thomas Edison )则将机械工程的“小故障和困难”描述为“错误” 。

同样,在进入计算机世界之前,“调试”一词似乎已被用作航空的术语。在一次采访中,格雷斯·霍珀(Grace Hopper)表示,她没有创造这个词。飞蛾适合已经存在的术语,因此被保存了。 J. Robert Oppenheimer (新墨西哥州洛斯阿拉莫斯的第二次世界大战原子弹曼哈顿项目主任)的来信,在1944年10月27日给加州大学伯克利分校的Ernest Lawrence博士的一封信中使用了该术语职员。

牛津英语词典的“调试”文章引用了1945年《皇家航空学会杂志》一篇文章中用于飞机发动机测试的“调试”一词。 “ Airforce”中的一篇文章(1945年6月,第50页)也指调试,这次是飞机摄像机。 Hopper的错误是在1947年9月9日发现的。计算机程序员直到1950年代初才采用该术语。吉尔(Gill)在1951年的开创性文章是对编程错误的最早讨论,但它不使用“错误”或“调试”一词。在ACM的数字图书馆中,“调试”一词首先在1952年ACM全国会议的三篇论文中使用。这三个中的两个在引号中使用该术语。到1963年,“调试”是CTSS手册第1页的未说明的常用术语。

范围

随着软件和电子系统通常变得更加复杂,各种常见的调试技术已经扩展了更多的方法来检测异常,评估影响和安排软件补丁或对系统的完整更新。可以将单词“异常”和“差异”用作更中立的术语,以避免单词“错误”和“缺陷”或“错误”或“错误”,其中可能暗示所有所谓的错误缺陷错误必须固定(不惜一切代价)。取而代之的是,可以进行影响评估,以确定删除异常(或差异)是否对系统具有成本效益的更改,或者可能会导致预定的新版本可能导致不必要的更改。并非所有问题都是系统中关键关键任务的问题。同样,重要的是要避免发生变化对用户长期感到不安的情况,而不是解决已知问题的情况(“治愈将比疾病更糟”)。基于某些异常可接受性的决定可以避免“零缺失”任务的文化,在这种文化中,人们可能会诱使人们否认存在问题,从而将结果显示为零缺陷。考虑到附带问题,例如成本效益的影响评估,那么更广泛的调试技术将扩大以确定异常的频率(发生相同的“错误”)以帮助评估其对整体系统的影响。

工具

在视频游戏机上进行调试通常是使用特殊硬件(例如该Xbox调试单元供开发人员)完成的。

从修复简单错误到执行冗长而累人的数据收集,分析和调度更新的冗长而累人的任务的复杂性范围。程序员的调试技能可能是调试问题能力的主要因素,但是软件调试的困难与系统的复杂性差异很大,并且在某种程度上取决于所使用的编程语言。以及可用的工具,例如调试器。调试器是软件工具,使程序员能够监视程序的执行,将其停止,重新启动,设置断点并更改内存中的值。调试器一词也可以指在进行调试的人。

通常,高级编程语言(例如Java )使调试变得更加容易,因为它们具有异常处理类型检查之类的功能,这些功能使真实的行为源更加易于发现。在诸如C组件之类的编程语言中,错误可能会导致沉默的问题,例如内存腐败,通常很难看到最初的问题发生在哪里。在这种情况下,可能需要内存调试器工具。

在某些情况下,本质上特定语言的通用软件工具可能非常有用。这些采用静态代码分析工具的形式。这些工具在源代码中寻找一组非常具体的已知问题,有些常见和一些罕见的问题,更多地集中在语义上(例如数据流),而不是语法,而不是编译器和口译员。

各种语言都有商业和免费工具;有些人声称能够发现数百个不同的问题。检查非常大的源树时,这些工具可能非常有用,在该源树进行代码漫步是不切实际的。检测到的问题的一个典型示例将是在分配变量值之前发生的变量解除。作为另一个例子,某些这样的工具执行强大的类型检查,何时该语言不需要它。因此,他们更好地在句法正确的代码中找到可能的错误。但是这些工具具有误报的声誉,其中正确的代码被标记为可疑。旧的Unix绒布程序是一个早期的例子。

用于调试电子硬件(例如,计算机硬件)以及低级软件(例如, bioses设备驱动程序)和固件示波器逻辑分析仪电路模拟器(ICES)等仪器经常被使用,单独使用,单独使用或单独使用结合。 ICE可能会在低级软件固件上执行许多典型的软件调试器任务。

调试过程

调试过程通常始于确定重现问题的步骤。这可能是一项非平凡的任务,尤其是在平行过程和某些Heisenbugs的情况下。特定的用户环境和使用历史记录也可能使重现问题很难。

复制错误后,可能需要简化程序的输入,以使其更易于调试。例如,编译器中的错误可以使其在解析大源文件时崩溃。但是,在简化了测试用例后,原始源文件中只有很少的行足以重现同一崩溃。可以使用分界线和串扰方法手动完成简化,其中程序员试图删除原始测试用例的某些部分,然后检查问题是否仍然发生。当在GUI中调试时,程序员可以尝试跳过原始问题描述中的一些用户交互,以检查其余的操作是否足以导致错误发生。

经过充分简化测试案例后,程序员可以使用调试工具检查程序状态(变量的值,以及呼叫堆栈的值),并跟踪问题的起源。或者,可以使用跟踪。在简单的情况下,跟踪只是几个打印语句,它们在执行程序期间在特定点处输出变量值。

技术

  • 交互式调试使用调试器工具,该工具可以一次处理程序的执行,并暂停检查或更改其状态。子例程或函数调用通常可以全速执行,并在返回呼叫者或自己单步的后再次暂停,或这些选项的任何混合物。可以安装设定点,以全速执行不怀疑是故障的代码,然后停在一个点。在程序循环结束后立即将设定点放置是评估重复代码的便捷方法。观察点通常可用,执行可以继续进行,直到特定变量更改为止,并​​且导致调试器停止某些类型的程序事件(例如例外或共享库的加载)的关键点。
  • 打印调试跟踪是观察(实时或记录)跟踪语句或打印语句的行为,该行为指示过程的执行和数据进程的执行流。可以使用专用工具(例如使用GDB的跟踪)或将跟踪语句插入到源代码中进行跟踪。后者有时被称为printf调试,由于在C中使用了printf函数特隆代表“痕迹”。 TRON导致每个基本命令行的线号在程序运行时打印。
  • 活动跟踪就像跟踪(上图),但不是遵循程序执行一个指令或功能,而是根据处理器/CPU执行特定代码段所花费的整体时间遵循程序活动。通常将其作为程序在定义的内存地址(机器代码程序)或某些程序模块(高级语言或编译程序)中处理指令花费的执行时间的一部分。如果被调试的程序被证明是将其执行时间的过分分数花费在跟踪区域内,则可能表明由于程序逻辑错误导致的处理器时间的分配不当,或者至少可以从优化工作中受益的处理器时间效率低下。
  • 远程调试是在与调试器不同的系统上运行的程序调试程序的过程。要开始远程调试,调试器通过通信链接(例如局域网)连接到远程系统。然后,调试器可以控制远程系统上程序的执行,并检索有关其状态的信息。
  • 验尸后的调试是该程序已经崩溃后调试该程序。相关技术通常包括各种跟踪技术,例如检查日志文件,在崩溃中输出呼叫堆栈以及崩溃过程的内存转储(或核心转储)的分析。该过程的转储可以由系统自动获得(例如,当该过程因未经治疗的异常而终止时,或者由程序员插入的指令或由交互式用户手动手动。
  • “狼栅栏”算法:爱德华·高斯(Edward Gauss)在1982年的一篇文章中描述了这种简单但非常有用且著名的算法,以供ACM通讯,如下所示:在状态下,等待狼到how叫,确定围栏的哪一侧。这是在GIT版本控制系统中作为命令GIT二进制的,它使用上述算法来确定哪个提交引入了特定的错误。
  • 记录和重播调试是创建程序执行记录的技术(例如使用Mozilla的免费RR调试工具;启用可逆调试/执行),可以重播并进行互动调试。对于远程调试和调试间歇性,非确定性和其他难以产生的缺陷有用。
  • 时间旅行调试是通过源代码(例如使用undo liverecorder )回到及时回到的过程,以了解执行计算机程序期间正在发生的事情;允许用户与程序进行互动;如果需要,请更改历史记录,并观察程序的响应方式。
  • Delta调试- 一种自动化测试用例的技术简化技术。
  • SAFF挤压- 一种在测试中进行逐步隔离的技术,即在测试中进行隔离。
  • 因果跟踪:有一些技术来跟踪计算中的原因效应链。这些技术可以针对特定的错误进行量身定制,例如空指针呈现。

自动错误修复

自动解决方案是在没有人类程序员干预的情况下自动修复软件错误。它通常也称为自动补丁生成自动错误维修自动程序维修。此类技术的典型目标是自动生成正确的补丁程序,以消除软件程序中的错误而不会引起软件回归

调试嵌入式系统

与通用计算机软件设计环境相反,嵌入式环境的主要特征是开发人员可用的大量不同平台(CPU架构,供应商,操作系统及其变体)。从定义上讲,嵌入式系统不是通用设计:它们通常是针对单个任务(或少量任务)开发的,并且该平台是专门选择的,以优化该应用程序。对于嵌入式系统开发人员来说,这一事实不仅使生活变得艰难,而且还使对这些系统的调试和测试也更加困难,因为不同平台需要不同的调试工具。

尽管上面提到的异质性面临挑战,但一些辩论者和研究原型都在商业上开发。商业解决方案的示例来自Green Hills软件Lauterbach GmbH和Microchip的Mplab-ICD(用于电流内调试器)。研究原型工具的两个例子是Aveksha和Flocklab。他们都利用低成本嵌入式处理器上可用的功能,即芯片调试模块(OCDM),其信号通过标准JTAG接口暴露。根据需要对应用程序的更改以及他们可以跟上的事件的速度,它们是基准的。

除了识别系统中的错误的典型任务外,嵌入式系统调试还试图收集有关系统操作状态的信息,然后可以使用该系统来分析系统:找到提高其性能或优化其他重要重要性的方法特征(例如能源消耗,可靠性,实时响应等)。

反欺骗

反欺骗是“在计算机代码中实施了一种或多种技术,该技术阻碍了逆向工程或调试目标过程的尝试”。它在拷贝保护方案中被公认的发行商积极使用,但恶意软件也将其用于使其检测和消除复杂化。反欺骗中使用的技术包括:

  • 基于API的:检查使用系统信息是否存在调试器
  • 基于异常:检查异常是否干扰
  • 过程和线程块:检查过程和线程块是否已被操纵
  • 修改代码:检查调试器处理软件断点的代码修改
  • 基于硬件和寄存器:检查硬件断点和CPU寄存器
  • 时间和延迟:检查执行指令所花费的时间
  • 检测和惩罚调试器

Microsoft Word的早期版本中存在反欺骗的一个早期例子,如果检测到调试器,就会产生一条消息,说:“邪恶之树呈现出苦味的水果。磁盘驱动器以发出令人震惊的噪音,目的是吓到用户再次尝试。

也可以看看