【问题标题】:What do you do if you cannot resolve a bug? [closed]如果您无法解决错误怎么办? [关闭]
【发布时间】:2010-09-14 08:53:03
【问题描述】:

您的代码中是否有过无法解决的错误?我希望我不是唯一一个有这种经历的人......

存在一些难以追踪的错误类别:

  • 与时间相关的错误(例如发生在进程间通信期间)
  • 内存相关的错误(我猜你们中的大多数人都知道合适的例子!!!)
  • 与事件相关的错误(难以调试,因为您遇到的每个断点都会使您的 IDE 成为鼠标释放/焦点事件的目标...)
  • 与操作系统相关的错误
  • 硬件相关错误(发生在 释放机器,但未打开 开发者机器)
  • ...

说实话,有时我自己无法修复这样的错误......调试了几个小时(有时甚至几天)后,我感到非常沮丧。

在这种情况下你会做什么(除了向别人寻求帮助,这并不总是可行的)?

你呢

  • 使用铅笔和纸代替调试器
  • 面对另一件事并返回 稍后会出现这个错误
  • ...

请告诉我!

【问题讨论】:

  • 这可能因为过于宽泛而被关闭,但这是一个非常好的问题,永恒且相关。

标签: debugging


【解决方案1】:

一些有用的东西:

1) 休息一下,从不同的角度接近 bug。

2) 更积极地进行跟踪和日志记录。

3) 让另一双眼睛看着它。

4) 通常的最后手段是通过改变其发生的基本条件来找出一种方法使该错误无关紧要

5) 砸碎东西。 (仅缓解压力!)

【讨论】:

  • 就个人而言,#4 让我害怕。如果你不知道错误是什么,你怎么会知道你已经让它无关紧要了。
  • 当它不再发生时,它就变得无关紧要了。 ;)
  • 同意所有这些 - 数字 3 尤其重要。即使只是向某人解释它也会有所帮助(参见 Cardboard Dog)
  • 我还要在您的摘要中添加一件事(介于 2 和 3 之间)。暂时禁用一些代码,直到错误停止发生
【解决方案2】:

我曾经在一家销售客户端-服务器应用程序的公司工作,该应用程序基本上是一种文件传输和同步工具。客户端和服务器都是我们设计的自定义应用程序。

我们有一个难以在实验室中复制的持久性错误。我们的服务器每个盒子只能处理一定数量的传入客户端连接,因此我们的许多客户会将多个服务器“集群”在一起以处理大量用户群。集群的后端数据位于他们共享的文件服务器上。在此集群配置中,有一个错误会在负载下发生,我们会在涉及后端文件之一的文件共享调用中获得低级文件系统错误代码。没有人可以在实验室中可靠地重复此操作,即使可以,他们也无法缩小正在发生的事情的范围。

(我忘记了确切的错误,它可能是 59 ERROR_UNEXP_NET_ERR65 ERROR_NETWORK_ACCESS_DENIED。我记得它甚至不是您应该能够从我们调用的 API 获得的记录错误代码之一,这通常是对文件部分的锁定或解锁调用)。

由于它涉及服务器和后端文件存储之间的通信,而我是“网络传输”的人,我的任务是查看它。许多其他人都没有运气看过它。

我有一件可靠的事情是我知道在代码中的哪个位置检测到错误,但不知道该怎么做。所以我需要找到根本原因。因此,我设置了一个适当的硬件环境来复制它,并且我放置了一个服务器软件的自定义版本,用于检测相关代码部分。

检测如下:我为麻烦的错误代码添加了一个测试,并让它在错误发生时调用一段代码将UDP数据包发送到预定的网络地址。 UDP 数据包中包含一个唯一的字符串,用于键入。

然后我在网络上设置了一个数据包嗅探工具。 (当时我使用的是Microsoft Network Monitor)。我将它放置在发送时能够“看到”这个 UDP 数据包以及集群服务器和文件服务器之间的所有通信的位置。

大多数优秀的嗅探器都有一种模式,您可以让它捕获,直到它看到特定的流量,然后停止。我打开了该模式并将其设置为查找我的代码将发送的 UDP 数据包。目标是在错误发生之前捕获所有文件服务器流量的数据包。传入和传出 UDP 数据包起源系统的最后一个网络数据包可能是了解正在发生的事情的重要线索。

我设置了“压力测试”配置并回家过周末。

当我周一回来时,你瞧,我拿到了我的数据。经过数小时的运行,嗅探器正如预期的那样停止并包含捕获。在研究了捕获后,我发现我们的服务器和文件服务器之间的Server Message Block or SMB(又名 CIFS 又名SAMBA)连接实际上在 TCP 级别由于极端负载而超时服务器。因为微软的所有东西都是高度分层的,它会通过文件共享堆栈作为“意外”错误进行备份,而不是返回一个更容易理解的错误代码,上面写着“嘿,你在 TCP 级别失去了连接”。

我对@9​​87654324@ 做了更多的研究,你瞧,我们使用的 Windows 版本的默认值(在那个时代可能是 NT 4)并不太慷慨。它只允许 TCP 连接和繁荣的极少数失败,你死了。一旦您失去了与文件服务器的 SMB 连接,您的所有文件锁都已失效,无法恢复。

所以我最终写了一个用户手册的附录,它解释了如何更改 Windows 中的 TCP 设置以使您的集群服务器更能容忍高负载情况。就是这样。该错误的修复是代码零更改,只是一些关于如何正确配置操作系统以供该产品使用的附加文档。

我们学到了什么?

  • 准备运行代码的更改版本来调查问题
  • 考虑使用非传统工具来解决问题(嗅探器)
  • 并非所有错误修复都需要更改代码
  • 有时您可以在家里喝啤酒时诊断出虫子

【讨论】:

  • 伟大的评论蒂姆。这是一个很好的例子,说明有时需要隔离一个困难的错误。
  • 我现在实际上正在经历类似的事情。嘿,这就是我们得到报酬的原因,对吧?
  • 并非所有错误修复都需要更改代码(即使是配置设置中的一些更改也可以修复错误)
【解决方案3】:

我做了很多不同的事情:

  • 抛开我所有的假设,从头开始。请记住,存在错误是因为看起来正确的东西实际上是错误的。即使您绝对确定正确的那些行或函数或类也可能不正确。除非你能说服自己是正确的,否则你不能假设任何事情都是正确的。

  • 继续添加 print 语句和 assert 语句以消除事物并让我重新假设。

  • 如果问题是控制流问题,则在调试器中单步执行代码。不要越过功能。介入他们并检查他们执行的所有细节,以确认他们工作正常。确认参数和返回值。

  • 如果某行、函数或类是可疑的,但我无法在现场证明它,那么编写一个小测试用例来执行您认为问题构造所做的事情。这可能会找出问题所在,或提供一些关于下一步该往哪里看的见解。

  • 今天停下来。令人惊讶的是,你的大脑会在一夜之间完成什么样的离线处理。通常,当我在做一些无意识的事情(如淋浴或开车)时,答案或关键见解会在第二天出现。

【讨论】:

    【解决方案4】:

    创建一种自动导致错误的方法。要修复的最糟糕的错误是需要数小时才能重现的错误。

    【讨论】:

      【解决方案5】:

      引自“The Cryptonomicon”:

      “直觉就像一道闪电,只持续一秒钟。它通常是在一个人被难以破译的折磨时,当一个人在脑海中回顾已经尝试过的徒劳无功的实验时。突然,光芒突破几分钟后,人们就会发现前几天的劳动无法揭示的东西。”

      【讨论】:

        【解决方案6】:

        我通常会请其他人看一下代码。当我解释代码应该做什么时,我有时会在我说话时看到错误。

        当一个 bug 很棘手时,我会坐下来工作,直到找出并解决问题。有趣的是,有时捕捉神秘的错误比一切顺利进行更令人愉快。以及当一个错误被解决时的解脱和感觉,嗯,没有多少其他事情能比得上这一点(除了那些显而易见的事情)。

        【解决方案7】:

        如果所有其他方法都失败了,请不要直接解决它。以更重构的方式重写问题区域代码。

        【讨论】:

          【解决方案8】:

          在找到解决方案之前,我已经连续工作了 4 到 5 天,确实遇到了一些错误。其他错误已经在错误跟踪器中放置了几个月,因为我花了几个小时在很长一段时间内分散。我认为这种错误在任何复杂的软件项目中都是不可避免的。

          一些对我有用的东西:

          • 使用日志记录在程序流中进行二进制搜索
          • 使用Trace 语句和 DbgView 来搜索在发布模式下出现的错误
          • 在不更改代码的情况下找到重现错误的替代方法
          • (不符合逻辑,但是...)更改代码,以便更容易重现错误(更容易实现故障条件)
          • 睡一觉,明天用一双新的眼睛再试一次:)

          在我看来,最糟糕的错误是并发错误,它会在插入日志记录时消失。

          【讨论】:

            【解决方案9】:

            这里有很多很棒的答案。过去对我有用的一件事是问“当这个问题发生时,我能做些什么来使它完全明显?”。

            例如,如果问题是数据结构中的值损坏,请尝试构建一个可以定期运行的一致性检查例程。还可以考虑通过一组记录每次更改的函数来实现对共享数据的所有访问。

            或者,如果问题是“随机”内存覆盖,请使用替代 malloc()/free() 实现来捕获写入“空闲”内存(如电子围栏或 dmalloc)。

            其他人提到自动化触发错误的过程。如果你能做到,那就太好了。在这些情况下,即使有一个随机锻炼程序的例程也可能会有所帮助。

            【讨论】:

              【解决方案10】:

              真的吗?我按这个顺序做事。

              1. 去睡觉
              2. 问问同事
              3. 重写,使该区域不受影响。
              4. 这样问
              5. 向您的第 3 方库供应商提出支持请求。

              【讨论】:

                【解决方案11】:

                “在这种情况下你会做什么(除了向别人寻求帮助,这并不总是可能的)?”

                什么时候不能寻求帮助?

                您总是可以向其他人寻求帮助——您的同事、您的老板、Stack Overflow 的朋友等等。

                了解何时寻求帮助不应令人沮丧!

                【讨论】:

                  【解决方案12】:

                  这里有很多很好的提示。

                  我绝对不同意的一个概念是更改代码希望它会消失的概念。首先,您可能会引入新的错误。几秒钟后,您可以轻松地更改足以隐藏错误的内容,只是让它在下一个补丁中再次出现。

                  内存损坏错误特别有可能像它们出现时一样神奇地消失。但是,内存损坏错误并没有修复,只是内存的非致命区域被丢弃了。

                  1) 尝试不同的调试器。例如,我越来越频繁地使用 WinDbg。当您在调试器中加载程序时,应用程序的内存布局会略有变化。也许不同的调试器会导致错误的表现方式略有不同。

                  2) 如果您在不确切知道问题所在的情况下更改代码,那么如果错误消失,您必须返回并了解更改修复错误的原因。否则,您可能只是在隐藏错误。

                  3) 与其他人讨论该错误,也许他们已经看到了同一问题的不同版本(即其他方法来重现它)

                  4) 日志记录。

                  【讨论】:

                    【解决方案13】:

                    我遇到过需要数周或数月才能找到解决方案的错误,但最终所有错误都会得到修复。除了经典的非调试器错误跟踪技术(例如在获得最小测试用例之前禁用系统的某些部分)之外,我还使用了以下技术:

                    • 寻找更好的调试工具。一个新的视角有很长的路要走。 Xdebug 是我开始在 PHP 中使用的东西,只是因为我没有取得进展的性能错误。

                    • 研究错误所在的技术。这有助于调试 Outlook 加载项。它有没有意义的随机错误,而且谷歌搜索出现了zilch。通过研究 Outlook 插件最佳实践、COM 和 MAPI 编程,我们更清楚地了解了可能出现的问题,并想到了尝试修复错误的新方法,最终确实修复了这些错误。

                    • 试图加剧问题。如果有一个问题只是偶尔发生,我会努力想办法让它不断发生。这有助于在 IE 下跟踪 Web 应用程序中的错误,并缩小 Flash 插件中的崩溃错误。

                    • 当所有其他方法都失败时,我从头开始重写了导致问题的子系统。这可能需要几天甚至几周的时间,但是如果您遇到错误并且无法解决它,并且客户不会拒绝回答,您还能做什么?这并不总能解决问题,但如果不能解决问题,您通常会更清楚地了解问题所在。

                    我注意到这些错误中的一些共同点,我被困了数周:

                    • 向第 3 方寻求帮助很少有帮助,而且等待其他人来挽救局面通常不是一个好主意。

                    • 故障几乎总是在某些第 3 方闭源技术内部,尤其是在使用不起眼的部件时。 IE 在尝试使用客户端证书时遇到了令人讨厌的错误。 Flash 不能很好地处理随机生成的绘图指令(其中一些是无意义的)。当您尝试从代码动态更改表单布局时,Outlook 不喜欢它。这些天来,我学会了尊重专有技术的“舒适区”。

                    【讨论】:

                      【解决方案14】:

                      我给它更多的时间。我曾经有一个我无法弄清楚的错误(在个人项目中)。我尝试了所有我能想到的调试方法,包括谷歌,但没有成功。六个月后,我回来并在一个小时左右的时间内发现了这个错误。这不是一件简单的事情(显然在 Swing 内部发生了一些没有记录的事情),但我只是以一种我以前没有的方式看待它。

                      【讨论】:

                      • +1:我同意你的观点,但是当管理层希望你赶上最后期限时,很难要求更多时间。我会承认,不可改变的最后期限是完全不同的问题。
                      【解决方案15】:

                      我以前也遇到过这个问题,相信大家都有,我之前已经彻底放弃了,根本找不到,但是一直崩溃,当代码中出现某种错误时,我所做的是只需坐下来一点一点地专注于代码的每一点,直到我找到它,这很难,而且需要耐心,但在这种情况下你只能这样做。

                      希望这会有所帮助。

                      【讨论】:

                        【解决方案16】:

                        老实说,我想不起我无法修复的错误。它可能会导致大量重构,或者可能需要一段时间,但我从来没有一个我无法摆脱的。如果我要花一个多小时才能找到它,那么它几乎总是真的愚蠢而渺小,就像看过去应该是 ;:,等等。 p>

                        在 python 中,如果我使用的不是我的编辑器,或者可能是其他人的代码,我在 vim 中使用 retab!,或者粘贴到类似 paste 的东西中检查缩进(如果我没有vim 可用)。

                        如果这不是一个破坏者/交易破坏者,那么我继续前进,并以一双新的眼睛回来。

                        哦,你可以永远永远有太多的日志记录。

                        【讨论】:

                          【解决方案17】:

                          我添加了尽可能多的调试(写入日志文件、消息框等)和测试。

                          我不认为这是你能找到的最糟糕的错误。最糟糕的是那些你无法确定地或在测试环境中重现的。

                          【讨论】:

                            【解决方案18】:

                            当无法解决错误时,我也会感到沮丧。通常当我遇到错误时,我只会记下我的发现并停止工作。我会跳到另一个更容易解决的错误,然后回到错误。通过这样做,我将有一个新的想法和态度来解决这个错误。有时,当您在错误上花费太多时间时,您可能倾向于使事情变得过于复杂。休息一下,有助于破墙。

                            RWendi

                            【讨论】:

                              【解决方案19】:

                              首先,它可以重现吗?如果是这样,那将是一个巨大的优势。我希望错误总是/永远不会发生……麻烦的是间歇性的错误。

                              这将取决于问题,但在我的商店,我们通常会标记团队这样的问题,认为 2 个头(或 3 个或 4 个)比 1 个更好。

                              有时错误甚至不会出现在我的代码中,但它通常是。有些问题是第三方库是罪魁祸首,或者是特定平台上的特定实现是原因 - 那些很臭。

                              我将使用任何东西来至少追踪它:调试器、跟踪输出等等。

                              通常,如果我可以将它隔离到一个类或模块中,我会编写一个测试工具来复制现实世界并尝试在那里复制它。我通常先编写测试代码,但有时存在尚未进行测试的遗留代码(或其他开发人员的代码)。

                              我通常会与团队和白板大声讨论设计和问题,任何不清楚的地方。通常,一旦我们作为一个群体讨论解决方案,它就会浮出水面。

                              我就是这么做的。

                              【讨论】:

                                【解决方案20】:

                                我通常会努力解决它。但是,如果在合理的时间窗口内无法做到这一点,我会在我睡觉的时候将它留给脑细胞解决它;)有时它会起作用......

                                【讨论】:

                                  【解决方案21】:

                                  我考虑在这个名为StackOverflow 的网站上寻求帮助...

                                  【讨论】:

                                    【解决方案22】:

                                    这就是我今天所做的......

                                    我调试 HW/SW 交互,并且它通常情况下日志记录(仪器)会更改或隐藏错误。因此,测试是“全速”执行的。我称这些虫子为“蟑螂”,因为它们会避开我能照到它们的任何光线。

                                    所以我必须:

                                    找到导致错误的事务。通过日志记录列出硬件交互(此测试通过,但它说明了流程)。

                                    仪器打印状态变化前后的bug。

                                    我现在要解决的错误当然是最坏的情况,因为硬件已锁定。硬件包括 CPU,所以它就像在一个光线充足的房间里,然后电源出现故障并且一片漆黑。

                                    我对内存有一个特殊的后门视图,但当然这也被锁定了。我尝试重启电源,希望内存能够保持足够长的非易失性以重新启用后门。没有这样的运气。不过这是可能的。

                                    我非常非常仔细地编写了描述此错误的所有步骤(哪些有效,哪些失败等)。将此发送给具有类似硬件的开发人员,以验证它不是我或我的硬件。

                                    我休息了几个小时,让这些信息稳定下来,看看其他地方是否有灯泡亮着。

                                    没有回复,这个bug是我来解决的……

                                    此硬件软件交互是一个循环,它会进行一些设置,然后进入一个轮询循环,该循环在事务完成时读取。应该发生许多事务。哪个交易失败?是第一个吗(表明我可以调试事务而不是硬件中的一些噪音)。它总是第 N 次交易吗?是什么让第 N 个不同于第一个或第 (N-1) 个。 SW 是单线程的,并且构建为可预测的。没有抢占,没有启用中断。

                                    这个软件以前用过,有什么新的吗?所有硬件都是新的。在这种情况下,所有的硅都是新的,因为它是一个 ASIC。甚至嵌入式 CPU 也是新的和定制的,因此 ISA 是新的。

                                    所以我怀疑一切,我是瞎子。我得偷偷靠近这只蟑螂。

                                    我只启用了报告软件轮询硬件完成的次数的日志。通过这种方式,第一个事务快速运行,我知道我在紧密的轮询循环中接触硬件的频率。测试通过。我知道这是第 N 笔交易,我记录了所有交易的最高轮询次数(可能是无意义的数据)。

                                    修改任何内容后,我必须将其放回原处以验证错误仍然存​​在。毕竟地球自转了,太阳风也没有那么强了;)

                                    查看了所有签到,看到一个承包商更改了一些重要的设置参数,没有任何解释。这些(外包)人员仍在评估中。这无济于事。

                                    发现轮询循环中没有 spinwait。循环超时不好,因为没有它,超时取决于 CPU 速度。添加了spinwait,仍然没有快乐。

                                    限制事务的数量以查看失败的位置,在 1000 之前。

                                    将硬件设置为运行较慢,仍然挂起。

                                    不想让任何人读到这篇文章,但这种谩骂必须等到明天。

                                    【讨论】:

                                      【解决方案23】:

                                      没有无法修复的错误,因为没有完全重写无法修复的错误。

                                      无法修复的错误只是您不愿意替换的错误。

                                      【讨论】:

                                      • 如果可以的话,我会反对自己的浮夸。
                                      【解决方案24】:

                                      对于与内存相关的错误,我发现 Ants Profiler 的内存分析选项对我发现错误有很大帮助。

                                      【讨论】:

                                        【解决方案25】:

                                        使用更多创造性的方法来追踪错误。

                                        在可重现的机器上使用远程调试。

                                        使用分析工具。

                                        为应用引入更多日志记录。

                                        【讨论】:

                                          【解决方案26】:

                                          暂时离开,然后再回到问题上是我经常使用和听到的一种常见方法。

                                          错误重现的难易程度也是一个因素,因为如果错误只发生在程序的无数次运行中,那么通过破坏其他东西来修复它可能被认为是微不足道的收益。

                                          还有一个问题是确定错误在哪里,它是否存在于某些配置中,以便它发生在服务器上,而不是我运行 IIS 5.0 的本地 XP Pro 机器上。其他一些错误可能涉及必须更改我的机器的分辨率,这可能很烦人,试图重现其他人报告的错误。

                                          您忽略了“在另一个操作系统下发生”类别的错误,因此在 PC 上的 IE 和 Firefox 中正常的网页可能在 Mac 上的 Safari 上看起来像垃圾。在尝试使用我的机器作为服务器和在地板隔间中超过一两排的 Mac 来解决 CSS 问题时,我是不是弄脏了手才能看到这个问题,还是它的优先级太低了席卷地毯?或者,如果 Linux 上出现错误并且我附近没有任何 Linux 机器,我该怎么办?

                                          很抱歉留下了一些问题,但这些问题有时对我来说似乎很困难。

                                          【讨论】:

                                            【解决方案27】:

                                            除了调试器之外,我还使用了日志记录和老式纸笔。有时我会发现非常棘手的错误,例如在调试模式下运行良好但在发布模式下中断的代码。我什至偶尔会重写非常好的代码,但无论出于何种原因,它都不能可靠地工作,我认为可靠比优雅更好。

                                            我有时会尝试将其他人所说的错误重新定义为真正的功能,但这很少奏效!

                                            【讨论】:

                                              【解决方案28】:

                                              我有一个错误,每隔几个月就会在客户网站上出现一次。它通常发生在凌晨 3 点,直到第二天早上客户到达他们的站点时才被发现。通常当他们发现它时,他们希望一切都立即开始工作,因此我们的支持人员通常只需重新启动计算机。多年来,它一直让我发疯。在我的测试机器或 QA 实验室中,它永远不会发生,只会在某些客户站点发生。随着时间的推移,我已经

                                              • 重构了一些我认为导致它的代码
                                              • 在崩溃的地方添加了更多调试打印输出
                                              • 重定向标准输出,以便下次我看到它时可以“kill -3”进程
                                              • 支持一些新工具来转储数据库锁等的当前状态。
                                              • 添加了诊断功能,使其在发生时更加明显

                                              这几个月没有发生过,我很高兴这次我可能会修复它,但我不指望它。

                                              【讨论】:

                                                【解决方案29】:

                                                如果不是很关键,就不要修复它,你只会花太多时间!

                                                保持漏洞打开。尽可能评论/工作。以后可能会意外(或由其他人)修复!

                                                【讨论】:

                                                  【解决方案30】:

                                                  有时需要一点横向思考,但每个错误都是可以修复的。有时你需要离开它并在上面睡觉,有时最好让其他人快速看一下(他们可能会看到你没有看到的东西),但主要是尝试不同的事情,调用以前的经验。这可能会令人沮丧,但是当你修复它时,你会得到的嗡嗡声是独一无二的!

                                                  【讨论】:

                                                    猜你喜欢
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    • 2022-01-22
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    • 1970-01-01
                                                    相关资源
                                                    最近更新 更多