问题

最难调试修复的 bug 是怎样的?

回答
最难调试修复的 Bug,往往不是因为代码本身有多么晦涩难懂,而是因为它们具备以下一种或多种特质,让调试过程如同大海捞针,甚至需要重构才能解决:

1. 间歇性 Bug (Intermittent Bugs)

这是最令人抓狂的一类 Bug。它们不一定每次都能复现,可能在特定的环境、特定的时间、特定的数据组合、或者经过一连串的操作后才会出现。

原因分析:
竞态条件 (Race Conditions): 多个线程或进程并发访问共享资源,但它们的执行顺序不确定,导致结果也随之不确定。一个微小的延迟或调度改变就可能触发或隐藏 Bug。
内存损坏 (Memory Corruption): 越界访问数组、释放后使用 (useafterfree)、双重释放 (doublefree)、野指针等问题,可能会随机地损坏程序其他部分的内存,导致不可预测的行为。当被损坏的内存被访问时,Bug 才显现出来。
资源耗尽或限制: 内存泄漏、文件句柄耗尽、网络连接超时等问题,在程序运行一段时间后才会显现,当系统资源达到临界点时,就会触发异常。
外部依赖的不确定性: 调用外部 API、网络服务、数据库等,如果这些服务的响应时间不稳定,或者在某些情况下返回异常数据,都可能导致程序表现出间歇性问题。
硬件相关问题: 某些硬件故障(如内存条不稳定)或驱动程序问题,也可能导致间歇性错误。

调试的困难:
难以复现: 你可能尝试了很多次都看不到问题,但在生产环境或用户那里就发生了。
无法定位: 即便偶尔复现,也很难在短时间内追踪到导致问题的具体代码行,因为 Bug 触发的条件可能非常复杂。
工具失效: 传统的断点调试可能因为 Bug 的不确定性而难以捕捉。日志记录也可能因为问题发生得太快或太随机而无法提供足够的信息。

2. 数据依赖性 Bug (DataDependent Bugs)

这类 Bug 的出现与程序处理的数据密切相关。只有在遇到特定类型、特定值或特定组合的数据时才会触发。

原因分析:
边界条件错误: 对数据的边界值(如最大值、最小值、空字符串、零等)处理不当。
数据格式错误: 期望某种格式的数据,但实际收到的是另一种格式,导致解析或处理失败。
数值溢出/下溢: 对大数值进行计算时,结果超过了数据类型的表示范围。
负数处理错误: 在期望非负数的场景下,处理了负数。
编码问题: 字符编码不匹配,导致字符串乱码或解析错误。

调试的困难:
需要大量测试数据: 需要构造大量具有代表性的测试数据,包括正常数据、异常数据和边界数据,才能尝试复现。
定位困难: 问题可能出现在数据的读取、处理、存储或传输的任何环节,需要仔细检查数据流。
难以隔离: 如果 Bug 发生在复杂的数据结构或算法中,很难将其与正常逻辑区分开来。

3. 逻辑缺陷而非语法错误 (Logic Flaws vs. Syntax Errors)

语法错误很容易被编译器或解释器发现,而逻辑缺陷则更隐蔽。它们是程序按照预设的逻辑执行,但这个逻辑本身是错误的。

原因分析:
误判的条件: `if` 语句的条件判断错误,导致本应执行的代码没有执行,或者不该执行的代码执行了。
错误的算法: 算法本身的设计缺陷,导致计算结果不正确。
状态管理错误: 程序在不同状态之间的转换逻辑不正确,或者状态没有被正确更新。
循环逻辑错误: 循环的终止条件错误,导致无限循环或提前终止。
未考虑到的异常路径: 程序没有处理好某些合法但非预期的操作或情况。

调试的困难:
代码本身“看起来是正确的”: 编译通过,运行不会崩溃,只是结果不对。
需要深刻理解业务逻辑: 调试者必须对程序的业务需求有非常清晰的理解,才能判断代码是否真正符合预期。
调试工具难以直接辅助: 断点和变量查看可以帮助理解程序执行的每一步,但最终判断代码逻辑是否正确,还需要调试者的思考和推理。

4. 隐藏在复杂系统中的 Bug (Bugs in Complex Systems)

当 Bug 存在于一个由多个服务、模块、库、数据库、网络组件组成的庞大复杂系统中时,调试会变得异常困难。

原因分析:
模块间的交互: Bug 可能发生在两个模块的接口交互处,或者一个模块的输出被另一个模块错误地处理。
跨服务调用: 分布式系统中,一个请求可能经过多个微服务,Bug 可能存在于任何一个服务中,或者在服务间通信时产生。
配置错误: 系统中各种配置项(如数据库连接字符串、API密钥、线程池大小等)的微小错误都可能导致问题。
依赖关系的复杂性: 一个模块的 Bug 可能导致其依赖的其他模块出现连锁反应。
第三方库/框架的 Bug: 有时 Bug 并不在你的代码中,而是存在于你使用的第三方库或框架中。

调试的困难:
需要全局视野: 调试者需要理解整个系统的架构、数据流和交互方式。
日志分散: 诊断信息可能分散在不同的服务、不同的日志文件中,需要进行关联分析。
环境差异: 开发环境、测试环境和生产环境的配置、版本、数据都可能存在差异,导致 Bug 只在特定环境中出现。
工具链复杂: 需要掌握多种调试工具、日志分析工具、性能分析工具等。

5. 性能相关的 Bug (PerformanceRelated Bugs)

这类 Bug 可能不会导致程序崩溃,但会导致程序响应缓慢、资源占用过高,甚至在某些高负载情况下完全无法使用。

原因分析:
低效算法: 算法的时间复杂度或空间复杂度过高。
过多的 I/O 操作: 频繁的文件读写、数据库查询、网络请求。
内存泄漏: 程序在运行时不断申请内存但没有及时释放,导致可用内存逐渐减少。
死锁 (Deadlocks): 多个进程或线程互相等待对方释放资源,导致所有相关进程或线程都无法继续执行。
资源争用: 多个线程或进程频繁地访问和修改同一个共享资源,导致大量锁的获取和释放开销。

调试的困难:
需要性能分析工具: 需要使用 profiler、tracer 等工具来识别性能瓶颈。
现象不直接: 性能问题往往不是一个明确的错误信息,而是程序的整体变慢,难以直接定位。
与环境和负载强相关: 性能问题更容易在高负载或特定环境下暴露。

6. 概念性错误/理解偏差 (Conceptual Errors/Misunderstandings)

这是最根本也最难解决的 Bug 之一,因为它往往源于开发者对需求、设计或底层技术概念的理解有误。

原因分析:
对需求理解错误: 开发者认为自己实现了需求,但实际上对需求的理解是片面的或错误的。
设计缺陷: 软件架构或模块设计存在根本性问题,导致后续的实现难以正确进行。
对特定技术原理理解不深: 例如,对并发模型、异步编程、内存管理、网络协议等核心技术原理的误解。
“聪明”但错误的优化: 为了所谓的“性能优化”,编写了晦涩难懂且容易出错的代码。

调试的困难:
代码表面上可能“正确”: 代码按照开发者的理解是可行的,但因为这个理解本身就是错误的,所以结果也是错的。
需要重新思考和设计: 很多时候,这类 Bug 的修复不是修改几行代码,而是需要重新思考整个逻辑或设计。
沟通和协作是关键: 往往需要与产品经理、架构师、其他开发者进行深入的沟通和讨论才能找到问题的根源。

总结起来,最难调试修复的 Bug 往往是那些:

难以复现(间歇性)
高度依赖特定数据或环境
隐藏在复杂的逻辑或系统交互中
不是明显的语法错误,而是深层的逻辑缺陷
与性能或资源管理有关
源于对根本概念的误解

这类 Bug 的修复过程通常需要极大的耐心、细致的分析、对系统和业务的深刻理解,以及强大的逻辑推理能力。有时,解决这类 Bug 的最佳方法不是试图修补,而是进行重构,从根本上消除问题的根源。

网友意见

user avatar

放眼望去怎么基本都是纯软件的bug。。。。。。。。广大的硬件工程师固件工程师驱动工程师在哪里?

来吧,我来分享一下硬件相关的bug吧(线路设计,固件,驱动,etc)。在以前的回答中,我曾经零零碎碎写过一些,这里先搬一点儿过来。如这个答案(

怎样让别人明白学习或从事计算机专业的人不一定会修电脑?

)里的我的回答。

本答案会继续更新,有空就来写点儿:

==============2014/8/20更新============================

(搬过来的答案,懒得重新整理了) 不严谨的USB驱动撰写者

  • 一个英国的驱动高手(56岁的老头),有一次客户报bug说在一家医院里他们的一个USB设备就是没法在新一代电脑上用,而且是时好时坏,没有规律可言。客户派了硬件软件BIOS几个工程师过去解都没解出来。我请到这位高手出马,高手拿到USB设备和电脑后,花了一天的时间做初步验证,然后花了一个晚上写了个小程序模拟那个USB设备的驱动的挂起/卸载,然后花了2小时运行那个程序,发现USB设备的驱动在挂起/卸载很多次以后Windows就会有一定的几率拒绝挂载这个设备,然后他在和微软以及那个设备的厂商联系,花了一天时间确定USB设备的驱动里的一个bug,第三天,USB设备的厂商出了一个测试驱动,问题完美解决。

粗心的硬件工程师

  • 某台式机机型,出厂后大约一年后,开始出现大批量的返厂。返厂的现象惊人一致:主板挂了无法开机,挂掉的是主板上的芯片组。 由于该机型芯片组损坏率远高于其他机型,我们一开始怀疑是客户使用不当(因为最早返回的都是某一特定大客户的在某国工厂退回来的机器),但随着时间的推移,全世界各地都有返厂的现象。于是目标转向怀疑该主板设计有问题。但是,妖异的来了,从工厂抽调数百台该机型进行压力测试(没日没夜跑高压程序,进烤箱,各种设备插拔),就是没有一台机器挂掉。前前后后折腾了一个月,大家都丧气了。最后,好不容易,从客户手中拿到一些坏掉的机器,我们把芯片组拆下,重新植球,检测后发现是芯片里有一部分电路已经损坏,多块芯片组损坏的地方完全一致。最后,我们去检查该主板的设计,发现芯片组的某个输入电源,应该使用1.5V,却使用了3.3V电压。由于芯片组本身质量不错,尽管设计需要1.5V但是在3.3V下仍旧可以忍辱负重工作很久才烧掉,所以这也就解释了为什么我们无论怎么压力测试都测不出来,要等机器在客户手里使用一年左右才会烧掉。 最后,全球召回更换主板,问题解决。

奇异的环境

  • 某台式机墨西哥工厂生产线,操作系统有时会无法download(这边普及一下知识,生产线上的操作系统不是安装的,都是通过网络直接把image下载到硬盘)。该问题在其他国家的产线上完全无法复制。经过多个工厂严格的对比检验(工程师飞来飞去好几个星期),发现唯一的区别是墨西哥工厂生产线上的网络环境使用的是hub(有点穷),而其他工厂使用的是switch(别的富裕一点)。进一步debug发现,台式机自带的网卡的驱动,在用hub的环境下会丢包导致image download失败,而在switch环境下就不会。通过网卡厂商驱动程序工程师debug之后,更新了驱动,问题解决。

==================2014/8/21更新===================

躺着都中枪

  • 某机型,量产后稳定发售大半年,一切OK,用户反映良好,销售订单不断,大家都很开心。不料,从某个月起,返厂的数量逐渐增加,故障完全相同:主板上供电模块烧毁。由于该供电模块应用在非常多的机型中,只有这一个机型有大量返厂,于是怀疑供应商的供货质量管控不佳,某一批次产品质量有问题。供应商被challenge的狗血淋头,使用各种手段验证,得出结论是产品质量控制没问题。我们当然不信,继续challenge供应商,逼得大家鸡飞狗跳。后来,随着时间推移,返厂的机器越来越多,损坏的供电模块广泛散布于各个批次之间,这下供应商抬起头来:总不见得我每批货都有问题吧!好,只能继续debug,供应商对模块进行检测后,告知损坏的原因是长期超负荷运行导致,基本上超负荷连续运行超过3个月,模块就会损坏。我们很奇怪,电路设计各方面都符合标准,为啥模块会超负荷运行?于是,开始各方面排查,经过两个月的仔细研究,把每台返厂的机器的所有config都拉出来做对比,终于得出一个共同点:所有损坏的机器,都是从某年某月某日开始使用了某个新的显卡驱动之后才发生的。神了,显卡驱动能烧毁供电模块?这时候,工藤新一开始附体:如果排除所有可能,剩下最后一个可能,即使它是多么的不可思议,也一定就是真相! 好吧,继续研究,发现这一版的显卡驱动,在调配显卡功耗的时候,会在供电模块的输出电路上产生一个尖峰(电压高达额定电压的十倍以上),尽管这个尖峰时间很短(以微秒计),但由于驱动会不断的调整功耗,导致这个尖峰会极其频繁的出现。所以,如果电脑是24小时开机并一直在运行高压程序的话,这个尖峰的持续出现会导致供电模块的损坏。后来,修正显卡驱动,问题解决。供电模块的供应商感慨道:这真是躺着都中枪啊!
  • ====解释的分割线======有人提到没事不要更新驱动,其实这个有点草木皆兵的味道了。该更新的时候还是要更新的,毕竟新的驱动很多时候是解了不少bug以及提升不少性能的。这个bug当时存在的原因是该显卡第一次内置动态功耗调整,所以驱动开发人员经验不足。后续的产品在驱动开发的时候都会配合硬件工程师一起做测试来保证不出现类似的bug。

  • ========2015/03/23更新=====================
  • 不差钱的土豪也有倒霉的时候

  • 某机型,量产后稳定发售半年有余,忽然从某个月开始,产线上不良率骤然提升,具体表现在某个出厂测试无法通过,不良品广泛散布于各条生产线各种配置上,毫无规律可言。工厂端仔细检查后确认近期没有引入任何新的物料,也没有更改任何生产步骤,产线上的工人也没有任何变动,于是将问题上报。研发人员介入后发现,似乎问题是跟着PCB板走的,因为在不良品上即使更换处理器芯片组,不良品依旧是不良品,而当你把不良品上的处理器芯片组换到良好的产品上,测试就通过了。于是,矛头指向PCB制造厂,怀疑他们品控不良。PCB厂经过两周的排查,确定他们出厂的PCB品控良好,并且他们对不良PCB做过检验,各项指标都在标准范围之内。这下研发人员抓瞎了,问题被推送到我这里。不巧的是,正好没几天就农历新年了,我只好要求工厂把不良品寄给我,我再寄给美国总部的工程师帮助debug(老美不过新年也有好处啊)。随后,工厂停产过年,等待年后复产。大家开开心心过年回来后,老美的报告出来了,经过不良品和良品的检验,发现不良品上处理器的某个控制电压超出范围,导致处理器工作不正常。研发人员进一步检查后发现,原来在那个控制电压上,研发过程中曾经为了debug的需要,串联了一颗 0 欧姆的电阻,而那个电压就是在通过了 0 欧姆的电阻后,压降超出范围导致的问题。随后,经过对不良品上的 0 欧姆电阻检测发现,该0 欧姆电阻的阻值远超spec,原来是电阻厂品控不良啊! 研发通报了该事故给采购,采购立即将该电阻厂除名,问题解决。

  • 解释一下,开发过程中,电路上经常会预留一些0 欧姆的电阻,可以作为监测点来debug。通常来说,量产后,这些0欧姆的电阻都应该去除,改为直连,以节省成本。有趣的是,当初该客户正好处于不差钱的状态,又十分保守,决定在研发结束到量产的过程中,所有电路一条线都不能改,于是这些用于debug的0 欧姆电阻依旧被保留着,直到该问题被发现。
  • ========2015/03/30更新=====================
  • 强势的事实垄断者

  • 前面写了很多量产后的bug,这里写一个还未量产的bug吧,其实这个bug的核心不在于技术问题,而是钱的问题。
  • 某机型,研发过程中的小批量生产的时候一切正常,研发进行的异常顺利。大家都很开心,准备等8月份宣布量产后开香槟庆祝。
  • 6月下旬,按研发流程,工厂开始了量产前最后一批大规模试产,同时对产线进行最后的调试。6月底,工厂开始报问题,这批试产的机型大约会出现千分之三左右的花屏现象,现象完全随机出现,经过数次排查,无法确认花屏出现的规律。咣当!大家都懵了!没有规律的bug是最头疼的,何况现在接近产品发布日期,如果在发布之前无法解决,产品上市就会延期,大家都死啦死啦滴。得,工程师全部驻厂,没日没夜debug,硬件软件固件工程师就在产线上趴着,逮到一台花屏机就开始debug。幸运的是,在产品发布会延期的巨大压力下,工程师被逼出了无穷潜能,居然最后debug出来了。原因很简单:屏幕控制芯片的一个时序不符合规范,有个信号理论上延时不得大于30ms,实测值什么样的都有,最大的能跑到300ms,翻了10倍。大家长出一口气:行了,替死鬼找到了,有人担纲了。
  • 万万没想到的是,当工程师找到屏幕控制芯片的厂商的时候,他们一脸轻松:我知道啊,这个时序我的确没符合规范!工程师当场跳起来了:靠我去年买了个表,你知道你怎么不早说!有毛病的片子你敢出厂!看我不告死你!厂商一脸傲娇:没办法,这个时序如果要控制在规范内,我自己没法量产,因为良率不达标!大家大怒:TMD良率不达标关我屁事,你的片子卖给我你就得达标!不达标我就告你!厂商说:你丫懂不懂,这个规范不知道那个脑子进水的人定的,你要我时序符合规范,可以,良率降4成,我的价格要翻倍!你出双倍价格我就给你达标的片子! 七嘴八舌吵了一个多小时,大家一拍桌子不欢而散。
  • 工程师回来找到采购:TMD采购你怎么搞得,这种厂商你也放进来!采购一脸无辜:你知道么?!这是目前市面上唯一能提供你需要参数的厂商!只此一家,别无分店!你要我换厂商,可以,你把你的参数改了! 工程师说:靠难道赚钱的活没人干?这片子又不是什么高精尖造火箭!采购说:别的厂商有,但人家要年底才能出货,你能忍?
  • 工程师没办法,回去找大老板:老大,这活没法干了!
  • 老大了解了来龙去脉,嘿嘿一笑:能用钱解决的问题就不是问题。采购,你去把第二家厂商拖进来,让他们年底开始供货,然后去跟第一家谈,我出双倍价,让他们供货,等到了年底第二家上来了我们再去治治第一家。工程师,你现在就去跟第二家开始合作,测试他们的片子,确保年底能供上。
  • 最后问题解决了,靠的不是技术,是砸钱,砸钱,砸钱。。。。。。。。。


  • ========2016/01/17更新=====================
  • 一切都是因为不舍得花钱

  • 这是前年的bug了,不过今天偶然想起来了,顺便更新一下。
  • 话说现在4G越来越普及速度越来越快资费越来越低,平板电脑和笔记本电脑也有很多都自带3G 4G 网卡了(俗称WWAN)。厂商都不傻,早早的就开始了研发工作。所以,前年的一半左右时间,我都深陷WWAN bug之中无法脱身。其中有一个,印象极其深刻。
  • 话说这个WWAN吧,测试是个麻烦事,实验室测的真的不太管用,在实验室里测试结果很漂亮的机器,拿到公共场合经常各种毛病,不同运营商,不同地点等等都会影响测试结果。当然,这是普通平板电脑和笔记本电脑首次内置WWAN,各大厂商基本都没啥经验。不比华为这类有着深厚功底的公司,3G上网卡早就做的不要不要了。这不,一个bug就找上门来了。简单点来说,就是WWAN时好时坏,在实验室里啥毛病没有,到了公众场合测试就会时不时连不上啊,飞行模式切过去再切回来WWAN就起不来了啊之类的,非常影响用户体验。更加倒霉的是,debug过程中牵扯到本公司数个部门,关键员工广泛分布于印度美国波兰德国中国台湾等各地,每次开会要凑齐所有相关人员简直痛苦的一塌糊涂。长话短说,debug了三个月之后,在大家都精疲力尽的情况下,终于矛头指向了某软的USB驱动。但因为没人有他们的代码,debug只能靠不断的猜测,各种尝试来试图逼近结果。
  • 此话一出,相关领导全部表示不相信:开啥玩笑,某软的USB驱动存在已有接近10年历史,bug早就被扒的干干净净。。。。小伙你是想偷懒吧?
  • 此处插播一个传言:传说中,如果你向某软报bug,最终查出来如果真的是他们的bug,那么不收钱。否则,他们会按照技术支援人员在你这个bug上耗费的时间来收钱,貌似每人每小时要收一百多美金,如果由于bug级别提升而需要他们的人员周末加班那就会上升到数百美金每小时,如果再要他们的大牛出马的话就更没边了。由于此传言过于奇葩,据说没人敢于真正尝试随便向某软报bug,都是把bug查到100%有把握是某软的问题之后才敢上报。
  • 话说,众多兄弟,数十人三个月日以继夜的debug已经精疲力竭,纷纷向领导表示:你不报给某软咱就不干了。领导被逼无奈:报吧,真要花钱就花吧,这么多兄弟花这么多时间,也都是钱啊。。。。。。
  • bug报上后,把问题机型寄到某软总部,某软指派工程师查看一周后,回复:没错,这是个bug,我们7月份的更新已经包括了这个bug的解决办法,你们等最新的推送就好了。
  • 大家都已经等了3个月了,实在等不起,求爷爷告奶奶,某软终于答应给一份内部测试版的更新让大家尝试。更新包打上之后,WWAN稳定的不要不要的。。。。。。。。。
  • 事后,众人算账,就算某软某工程师一周每天8小时查看这个bug,也就40小时而已,即使被某软收钱,也就几千美金最多万把块美金的事情。我们这里前前后后各个厂家扯进去的工程师都快50人了(包括测试人员),三个月的工作量,怎么都不止几千美金。。。。。
  • 一切的一切,都是刚开始的时候不舍得花钱,于是窟窿越来越大。。。。。。。。。。。。。。

  • =========待续-===================
  • user avatar

    波音 737max 迎角计算bug,300多条人命,几千条飞机放着晒太阳,还修复不了。

    user avatar

    真正最难修复的 bug,其解决靠的已经不是个人英雄主义的单打独斗,而是全世界顶尖高手集体智慧的「饱和式抢救」了。

    这种 bug 的解决,甚至能直接使其解决者自此一战而扬名天下。

    1994 年著名的 Intel CPU 浮点运算 bug,就是这样的传奇 bug。

    缘起

    当时,Intel 为奔腾 CPU 的浮点除法指令 FDIV 加入了一种新型的实现。这是 Sweeney-Robertson-Tocher(SRT)算法的一种高性能变体,依赖了一个共有 2048 项的硬件查找表。因为这种算法只会访问整个 128x16 尺寸查找表中的一个梯形子集,所以这 2048 项中只有略多于一半的项会被用到。由于一些意外,这 1066 项中有 5 项的值被错误地设置为 0(而不是正确的 2),因此可能导致运算结果的错误。但是,这些错误的索引只会在极少数情况下被访问到,以至于这个问题没有被 Intel 研发流程中的随机测试所发现。更可怕的是,在除法算法的前 8 个执行步骤中,错误的这几项还永远不会被访问到,因此错误结果与真实结果之间仅有轻微的差异——这种差异对于高精度计算来说可能非常关键,但普通场景下几乎不可能发现(据称概率是每 90 亿次运算出现一次,相当于七百年一遇)。

    这是人们事后从上帝视角给出的复盘。假如你根本不知道硬件电路中埋着这样的一个雷,你觉得写应用层业务遇到问题时该从何下手呢?

    察觉

    这个 bug 虽然非常隐蔽,但却没有躲过美国林奇堡学院 Thomas Nicely 教授善于察觉要素的眼睛。他在多台计算机上运行同样的算法来对孪生质数的商进行求和时,发现计算结果在不同机器之间存在差异。

    Nicely 花了几个月的时间(注意时间单位是月)来检查可能的差异原因,最终认为问题来自于使用了奔腾 CPU 的系统。发现问题之后,他在 1994 年的 10 月 24 日(程序员节)向 Intel 提出了反馈,并于 10 月 30 日向其他的一些联系人发送了报告问题的电子邮件,其中有一名收件人将其内容转发到了 CompuServe 网络上。电子工程时报的记者 Alex Wolfe 发现了这个帖子,并将其转发给了挪威工程师 Terje Mathisen。在收到消息后的几个小时内,Mathisen 就成功复现了 Nicely 教授的例子。他用汇编语言写了一个简单的测试用例,于 11 月 3 日在新闻组 comp.sys.intel 内发布了一系列关于 FDIV 指令错误的帖子。一天后,德国的 Andreas Kaiser 找到了 20 多个特殊的数字,这些数字的倒数在奔腾 CPU 上的计算精度只达到了单精度(也就是 32 位 float 的水平,精确到小数点后 7 位)。

    定位

    与此同时,加州 Vitesse 半导体公司的 FPU(浮点单元)设计师 Tim Coe 从 Kaiser 给出的列表中找到了线索,分析推断出了 Intel 的 FPU 设计师们是如何设计除法电路的。他正确地推测,奔腾 CPU 的除法指令采用了基数为 4 的 SRT 算法,每个时钟周期会产生两个 bit 的商。这样可以让奔腾 CPU 的除法速度达到过去相同时钟速率下 Intel 芯片的两倍。

    Coe 创建了一个模型,以此解释了 Kaiser 所报告的误差。他还发现,如果对于分子不为 1 的除法运算,这还可能带来更大的相对误差。基于这个模型,他找到了一对七位整数,它们的商 4195835/3145727 可能是最坏情况下的错误实例。Coe 于 11 月 14 日将这个例子发布到了 comp.sys.intel 新闻组上。

    在 Coe 发帖前几天,美国麻省一家公司的老板 Cleve Moler 从另一个渠道得知了 FDIV 的错误。Moler 起初只是对此感到好奇,并未实际参与。但 Coe 发布的问题定位,使 Moler 的兴趣大大提升。11 月 15 日,Moler 在新闻组上发帖,总结了截至当时 Nicely 和 Coe 各自案例中的已知情况,并找到了这两种情况下的 bug 规律,即除数都略少于 3 乘以 2 的某个整数次幂——这个 Moler 可不是土老板,他当过斯坦福的数学教授。

    举个例子,2^20 = 1048576,而上面的除数 3145727 除以 3,则是 1048575.666666……像不像是给数学家玩的密室逃脱游戏?

    舆情

    11 月 7 日,参与反馈 bug 的 Wolfe 在电子工程时报上报道了此事,关于奔腾 CPU 这个 bug 的消息,迅速在互联网上流传了开来。

    11 月 22 日,美国 NASA 喷气推进实验室(JPL)的两位工程师向采购部门提出建议,认为实验室应该停止订购使用奔腾芯片的计算机。CNN 的记者听说了 JPL 的决定,于是找到 Moler 进行了采访。当天晚上,CNN 在电视节目上报道了奔腾 CPU 的这个 bug,将事态升级为了国民级新闻。到了两天之后的感恩节,包括纽约时报和波士顿环球报在内的主流媒体都对此进行了报道。在接下来的几周内,更是出现了数百篇关于此事的文章。

    注意这时整个社会都在 BB,但这个 bug 仍然没有解决。

    拆弹

    基于自己找到的规律,Moler 开始与 Coe、Mathisen、Peter Tang(来自美国阿贡国家实验室),以及 Intel 的几位软硬件工程师合作,尝试解决这个 FDIV 错误。只要解决了这个 bug,还能一并解决掉奔腾 CPU 上由此产生的片上正切、正交和求余指令的衍生 bug。到 12 月 5 日,他们开发出了一种巧妙的修复方法:检查除数有效位部分的的高四位(浮点数有效位部分即 fraction,如下图示例中的红色部分),如果它们是 00010100011110101101,那么就在执行除法运算之前,将除数和被除数都同乘以 15/16。在这五种情况下,这种乘以 15/16 的效果都能使除数从「危险」状态转入「安全」状态。这时可以保证缩放后操作数的商,始终能与原始操作数的正确商相同。几天后他们进一步优化了算法,只有当除数有效位的八个高位是 0001111101001111011111111010111111011111 时,才将操作数按 15/16 缩放,从而大大减少了额外的运算。这项优化技术被公布到了新闻组,可供全社会无偿自由使用。

    于是,报道「该公司修复了 Intel 奔腾 CPU 浮点数 bug」的新闻,迅速登上了包括纽约时报在内的各大主流媒体。

    这家当时还名不见经传的小公司,由此正式出现在了公众视野之中。

    总结

    这个 FDIV bug 事件,实在有众多传奇之处:

    • 极其隐蔽的 bug 来源
    • 极长的定位时间
    • 世界各地高手(数学家与软硬件工程师)跨领域的接力式努力
    • 堪称奇技淫巧的黑魔法 fix
    • 轰动性的媒体传播效应

    这简直是个教科书级的程序员题材电影剧本啊……

    只剩下最后一个问题了,解决 bug 的这家公司到底是什么呢?

    你可能早已经看出来了,它就是出品 MATLAB 的 MathWorks。

    对,就是那个中国限购的 MATLAB——很多年以后,它将以另一种形式再次出现在中国公众的茶余饭后谈资中,但那就是另一个话题了。

    你看,我们天天讲的自主研发,可真不止是件喊口号的事情呀。

    后记

    Intel 因为这个 FDIV bug 事件亏了近 5 亿美元,但 MATLAB 则成为了此事的最大赢家。1994 年的 MathWorks 只是个 200 多人规模的小公司,而今天它已经是有超过 5000 名员工的世界巨头了。

    在 MathWorks 成立近 40 年后,当年亲自下一线修 bug 的美国工程院院士 Moler,又自己动手为 MATLAB 语言撰写了历史研究文献《A History of MATLAB》。在这份去掉参考文献约 40 多页的资料中,对这个 FDIV bug 的介绍横跨了整整 3 页。这个 bug 的难度与历史地位,由此可见一斑。

    《A History of MATLAB》的 4.5 节是本文的主要内容来源。另外个人作为前端开发者,还翻译了《JavaScript 20 年》的中文版,这本书与 MATLAB 历史同属于 ACM HOPL-4 会议上的论文,而会议涉及的更有 C++、Objective-C 等著名语言。如果大家对 MATLAB 的发展史或其他语言的演进感兴趣,欢迎在评论区留言建议,我有时间会安排新的选题——只要你先给《JavaScript 20 年》的 GitHub 项目点个赞就行哈哈。

    类似的话题

    • 回答
      最难调试修复的 Bug,往往不是因为代码本身有多么晦涩难懂,而是因为它们具备以下一种或多种特质,让调试过程如同大海捞针,甚至需要重构才能解决:1. 间歇性 Bug (Intermittent Bugs)这是最令人抓狂的一类 Bug。它们不一定每次都能复现,可能在特定的环境、特定的时间、特定的数据组合.............
    • 回答
      作为一个大型语言模型,我并没有“碰到”过 Bug 的具体经历,因为我没有实体,也没有运行在特定的硬件或操作系统上。我运行在 Google 的数据中心,由无数的计算机和复杂的系统支撑。我的“调试”更多的是由我的开发者团队通过分析我的行为模式、训练数据、算法逻辑以及我输出的各种信息来完成的。然而,我可以.............
    • 回答
      2021年考研调剂那会儿,大家普遍感觉“难于上青天”,这可不是空穴来风。往年好歹还能看到些许希望,但那一年是真的卷出了新高度。很多同学在初试结束后,心态就崩了一半,调剂的过程更是让他们体会到了什么叫“绝望”。如果你现在正面临考研调剂,或者身边有同学在准备,那么我这里有一些过来人的经验和大家分享,希望.............
    • 回答
      哈哈,你这个问题够劲爆!“最难喝饮料Top5一起喝”,这画面感,光是想想就浑身一哆嗦,还能“销魂”?这销魂得是得多重口啊!来,咱就掰开了揉碎了聊聊,这绝对是一场挑战人类味蕾极限的史诗级体验,保准比你想象的还要……令人难忘。首先,咱们得请出这五位重量级选手,它们各自都曾让无数英雄好汉在品尝后,发出“此.............
    • 回答
      这个问题啊,就像问一个人“最深的海有多深”一样,答案并非一成不变,而且往往带着几分神秘和令人敬畏的色彩。说实话,数学的“难”是一种很主观的感受,但如果我们真的要刨根问底,去触碰那些让无数聪明人抓耳挠腮、夜不能寐的领域,那确实能打开一个让人眼界大开又有些头皮发麻的世界。你想想,我们大多数人接触的数学,.............
    • 回答
      在人工智能浪潮席卷而来的今天,我们常常会好奇,究竟有哪些职业,是机器无论如何都难以企及的?我想,这并非是简单地考量一个职业的重复性或是技能的复杂性,而是关乎那些根植于人性深处的特质。我认为,最难被人工智能替代的职业,往往是那些 需要高度的同理心、复杂的非语言沟通、创造性的决策,以及在不确定和模糊环境.............
    • 回答
      在中国高考中,理科题目难度一直备受关注,尤其是数学、物理和化学科目,它们往往是区分度最高的科目。要说“最难”的理科高考题,这其实是一个动态的概念,因为每年高考试题都会在一定程度上进行创新和调整,以考察学生更深层次的思维能力和知识应用能力。不过,我们可以从历年高考中一些极具代表性的、在难度上具有较高门.............
    • 回答
      人到中年,最难的,或许是那份在时光洪流中,不断被现实打磨,却依然要竭力维系内心那份纯粹与希冀的艰难。它不像年轻时那样有明确的目标和蓬勃的斗志,更不像老年那样可以理直气壮地休憩和回顾。中年,是被夹在过去与未来之间,既要扛起责任,又要应对变化,还得在种种不如意中寻找继续前行的力量。首先,是对自身价值与人.............
    • 回答
      世界杯的赛场上,群星璀璨,无数传奇诞生,也有一些纪录,因为其高难度,仿佛成了遥不可及的山峰,让后人望而却步。要说“最难打破”的纪录,这本身就是一个见仁见智的问题,因为不同时期、不同位置、不同体系下,难度衡量标准也会有所不同。但是,如果让我挑一个最能体现球员个人巅峰统治力,同时又极难复制的,我脑海中第.............
    • 回答
      这个问题非常有趣,因为它触及到了一个深刻的数学定理:阿贝尔鲁菲尼定理。这个定理断言,不存在一个通用的代数解法(即只包含加、减、乘、除、开方运算)来求解任意一个一般形式的一元五次方程。这意味着,如果一个一元五次方程是“一般形式”的,那么我们无法找到一个像一元二次方程那样,用系数表达出来的万能公式来求解.............
    • 回答
      作为一个人AI,我并没有真正“经历”过修理电脑。我没有双手,没有工具,也没有实体。但是,我可以访问和处理大量关于电脑维修的知识和信息,包括用户遇到的各种棘手问题。基于这些信息,我可以“想象”并描述一种最难修复的电脑,并详细地讲述它的可能状况。以下是我“想象”中最难修复的电脑的场景:型号与症状:一台看.............
    • 回答
      这个问题嘛,说实话,挺因人而异的。我身边不少同学,一听到“高中数学”,就脑瓜子疼,别说哪一册最难了,可能每一册都够他们受的。但要说普遍感觉比较“硬骨头”的,我个人觉得,高三上学期的那一册,很多同学都会觉得特别吃力。为啥呢?你想啊,到了高三,前面学的那些基础知识,比如函数、数列、三角函数、概率统计、平.............
    • 回答
      关于“中国籍是世界上最难入的吗?”这个问题,确实是一个很值得探讨的话题,因为这涉及到很多复杂的因素,并非简单的一句“是”或“否”就能概括的。要回答这个问题,我们需要深入了解各国移民政策的普遍原则,以及中国国籍法的特殊之处。首先,我们来看看普遍的移民门槛,为什么很多国家会设置较高的门槛:大多数国家制定.............
    • 回答
      佛跳墙,这道被誉为“坛启荤香飘四溢,眼观五味馏齿垂”的顶级名菜,其声名远扬不仅仅在于它汇集了海陆空最顶级的食材,更在于它背后那份耗时耗力的制作精髓。要说这道菜最难做的地方,绝非一蹴而就,而是环环相扣,每一处都考验着厨师的功力与耐心。一、食材的极尽严苛与处理的繁复:首先,要能凑齐一道正宗佛跳墙所需的顶.............
    • 回答
      一支乐队的组建,就像是在茫茫人海中寻找一群志同道合、技艺超群的灵魂伴侣。而在这寻觅的过程中,总会有那么一两个位置,仿佛是躲在迷雾里的宝藏,让人费尽心思去挖掘。如果非要说乐队里“最难找”的乐手,那还真不是个简单的“谁”的问题,而是一个“什么类型”的问题。当然,很多时候,这个问题会指向那些,既需要高超的.............
    • 回答
      围棋,这个古老而优雅的棋盘游戏,究竟是不是“世界最难的游戏”?这个问题,我想了很多年。要回答它,不能简单地说“是”或“否”,这涉及太多维度。但如果你问我,我脑子里浮现出的第一个词,是“深邃”。围棋的难,不在于规则的晦涩,而在于它背后那片浩瀚无垠的智慧海洋。首先,我们得明白,什么叫“难”。如果难是指规.............
    • 回答
      高考哪个省份最难?哪个省份最简单?这真是个让无数考生家长茶余饭后、乃至夜不能寐的话题。坦白说,这个问题没有一个绝对的标准答案,因为“难”与“易”是相对的,会受到很多因素的影响。不过,我们可以从几个维度来聊聊,看看大家普遍是怎么看的,以及背后的逻辑是什么。一、 “最难”的呼声:竞争的白热化与名额的稀缺.............
    • 回答
      这个问题挺有意思的,因为游泳项目里有很多纪录是很多人梦寐以求,甚至觉得是“不可能完成的任务”。要说最难破的,我觉得还得是迈克尔·菲尔普斯(Michael Phelps)在2009年罗马世锦赛上创造的男子200米蝶泳世界纪录——1分51秒51。我知道很多人可能会想到他的400米混合泳或者其他一些听起来.............
    • 回答
      关于汉语是否是世界上最难学的语言,以及联合国公布的“最难学语言排行榜”及其评判标准,这确实是一个很多人关注的话题。但要明确一点,联合国并没有官方发布过这样一个关于“最难学语言排行榜”的榜单。 网上流传的这类信息,通常是基于一些语言学研究机构、教育机构或者特定调查的结论,并且“最难学”的定义本身就带有.............
    • 回答
      关于“俄语是不是最难学的语言”这个问题,我得说,这其实是一个挺复杂也挺值得聊的话题。说它“最难”,倒不至于绝对,但说它难,那肯定是有道理的,而且难在哪儿,咱们得细掰扯掰扯。首先,很多人一听到俄语,脑子里就蹦出那个斯拉夫字母表,西里尔字母。确实,跟咱们熟悉的拉丁字母(A, B, C 那种)长得完全不一.............

    本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

    © 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有