你好!我很慢地写作一个关于调试的zine,所以我前几天问我:
如果你遇到了一个错误的错误,那里感到“不可能”了解正在发生的事情 - 是什么让它感到这种方式?
当然,错误总是发生逻辑原因,但我肯定会运行Intobums的觉得自己可能是不可能的,因为我可能是不可能理解的(直到剪影他们出来!)
我有大约400个回复,我将在这里汇总。我不会仔细训练如何处理这个不同的“不可能的”错误,我只需尝试对它们进行分类。
以下是我提出的类别,因为一个虫子可能会感到impossibleto了解。它们中的每一个都有一堆粗体粗体,如下粗体。
让我考虑职业变化的那些通常是错误的错误,即少数用户无法通过用户或在所有人的情况下一贯再现,并且在每个错误报告中具有略微不同的描述(有点像比侦察瞄准器)。
您可以使用完全相同的输入1000次运行程序,而且它只是ForeSonce。在多线程程序中,这与种族条件发生了很大的事情。
许多错误都很难在开发环境中重现,要么是因为它究竟要弄清楚哪个输入触发错误,或者因为它们在某些条件下(如很多流量),这是难以犯罪的条件下
您是在客户计算机上运行的运输软件(一个二进制或网站),他们遇到了问题,并且您没有直接访问他们的计算机,以查看正在发生的事情。
问题涉及一个托管云服务,您没有批量生产。
问题只在您无权访问的数据的输入上发生(可能是因为数据被分类/私有)
您无权访问您需要重现错误的数据
一个人提到了一个易于重现的错误,但是重现它所需的数据是保密的,所以他们不允许陷入困境。
有错误在哪里知道如何重现它,但它需要长时间(如20分钟或更长时间)来重现错误。这很难,因为很难保持你的焦点:也许你每天只能尝试1实验!
即使您可以重现错误,如果您不明白使用BUG工作的程序部分如何工作,您可以最终被困。
未知未知:该错误涉及您不了解的系统或概念
有时,错误是由您甚至不知道的系统的一部分引起的。例如,当我调试此TCP问题时,我从未听说过Nagle的算法或延迟ACK。所以要认识到他们造成问题是很有责任的!
我能够诊断那个虫子的唯一原因是,在工作中的某个人张贴了一个关于它的博客帖子,我记得症状恶化。
我在两个systemsthat之间发送了包含空字节(长故事)的字符串,而是在某些情况下,沿着沿着漏洞的方式进行一步
“错误在令人惊讶的地方”的另一个例子是扫描仪中的错误。
接下来的几个部分是更具体的方式对程序工作士的混淆使得一个难以解决的错误。
有时,错误是在图书馆或开放源程序中,你完全不熟悉,但你必须解决它。 这使得调试HRAD是因为: 修改库并获取程序并不总是容易使用您的图书馆的程序,因此很难尝试,并使更改为库添加额外的仪器 “β的值可能会引起DOM!”,从此通过标记allen在该错误消息上或 “尺寸必须在16793600(16MB)的第一元素:oints”从Kiran Bhattaram谈论诅咒的操作系统教科书的故事 如果您不知道他们的意思,一些编译器错误消息可能非常令人困惑 这些都很棘手,因为它不明确到哪里 - 什么是β? 这家元素在这里做了什么? 另一个变体是调试输出,以令人困惑的方式格式化。
有一个人提到的是:你搜索Youthink与你的错误有关的关键字,你得到1000万结果,其中没有任何帮助。
弄清楚一个陌生的系统已经很难,当你甚至没有阅读源代码时,它更糟糕!
有关系统的唯一信息来自您无法联系的人 - 仍然了解它已离开公司的人,或者您不知道WHOTHEY是,或者他们在公司工作,您无法找到任何联系信息
您需要的信息是在2000页的PDF中,您不知道Tostart看的位置
即使您普遍了解您使用的系统,并且您可以使错误提出错误,如果您在错误发生时无法获得有关程序的内部状态,则调试几乎是不可能的。
以下是一些具体原因,可以难以获取关于程序的内部状态的数据。
您的程序失败了,但根本没有输出才能读取,告诉您为什么它是它的。甚至没有错误消息!它只是不起作用。
这件事发生在我之前的操作系统错误 - 我的玩具操作系统没有,因为它在我有任何方式打印输出之前失败了,我有诺伊亚错了 - 它只是不起作用!
它也很容易淹没太多输出 - 我打开了调试输出,并完全不堪重负。这非常难以讲述有关的内容以及一百万个日志线的无关紧要!
调查分布式系统错误时,与Bugare相关的日志行经常分布在一堆不同的服务中。有时,您可以使用Norequest ID,您可以轻松地弄清楚来自服务的服务中的哪些日志行与您在服务B中看到的例外。
所以你最终花了很长时间手动盯着日志,并尝试他们试图他们。我花了更多的生活,这比我更喜欢:)
例如,如果您想了解数据库状态(如postgres),那么您肯定不会将调试器附加到您的Prodocuction数据库,并且您可能不希望重新编译它以添加extralogging信息。 (虽然我肯定地重新编译了我需要的addExtra日志信息的程序!)
因此,您需要依靠程序的现有日志机制,并希望其中有您需要的信息。
我在C ++代码中有一个错误,导致SEG故障。当我用调试标志编译时,它工作正常。真的很难找到。原来我是一个串,这是一个2个字节太大的字符串。调试标志为此创建extra空间!
调试器可能导致错误的另一个原因是如果它是一个racecondition - 调试器经常使程序运行一点点慢,an and the varause ant of the the vare。
在C或C ++ Printf中可以充当ad-hoc同步点/协作mtpoint,因此添加printf更改线程的执行顺序,使HOMPROBLAB消失。
例如,在几乎所有案例中,它是公平的,假设编译器不发布一个错误,并且错误在您的代码中。但是作为Twitter侧的人,很少是一个编译错误! (这是他们经历的编译器错误)
假设错误在硬件中的软件中(如同糟糕的电缆!)
让我们走一些“你的假设之一是错误”的变种。
有时你早早看到一些事情,看起来非常怀托,花了很长时间调查它,但事实证明了这虫子。这是非常正常的,它往往不是意味着你做错了一切(你不能采取完美的最有效的道路来了解每次的错误!)。但它可能真的很脏。
有效的情况和不起作用的情况看起来完全相同
当它发生时,这是如此令人沮丧 - 你100%肯定没有任何改变,以某种方式代码不再有效! (当然,答案是有些事情变化,你只是看不到它)
一个输入导致您的代码打破,但它成功地取决于一堆其他垃圾录,您无法弄清楚最新的输入的输入有所不同
一个非常小的代码变化导致了一个错误,你真的认为它应该有任何差异
完全相同的代码在相同的输入上运行,但有一些ExternalActor导致您未考虑的错误(如磁盘oran环境变量上的文件)
我们将谈论的最后一个类型是真正复杂的错误!
我想将这一个分开,因为很难理解的很多错误实际上都很简单!他们只是困难的Toundstand,因为上述一些原因(不正确的假设!你不了解系统!很难观察计划的状态!)。
太多,遥远的,对系统行为的影响不明。例如在图书馆中多次运行Amok
这并不总是意味着错误是复杂的,但它在0结果时令人震惊,或者有1个结果,它是......库的源代码,或者在论坛上发布了一个关于你的确切Bug的论坛的人员,但没有回复。(“哦,不,没有人曾经遇到过这个错误?!?!“)
大多数错误,只有一件事就是出错 - 除了1件事之外,系统中的一切都是正确的,你只需要识别出现问题的1件作品。
当多个东西立即破坏时,这可能会更加困难 - 也许程序中的错误,以及您使用的库中的错误,也是负载平衡器的一部分中的某种方式。
一个常见的例子是安全漏洞 - 他们往往涉及到很长时间的重写错误,即使你究竟弄清楚正在发生的事情也是如此。
这不是一个真正的技术原因,但棘手的虫子更困难地修复当你累了或漫长的一天后强调。
看到很多人都有相同类型的不可能的错误很有趣
我真的很高兴看到有多少人谈到了“不可能”虫子的原因。调试有时会感觉像一个非常激烈的个人斗殴(为什么这会发生在我身上?!?)我以为这真的很酷,甚至一些错误的最奇怪的原因是由很多人分享的。不止一个人提到“调试器会阻止来自嘻嘻的错误”!
我正在与我的合作伙伴聊天,在寻找几个月诊断的工作中的表现问题。 这是挑战性的,因为: 他们没有直接访问它正在发生的系统(它由供应商管理) 他们弄清楚了,但因为有很多事情让它变得困难,所以花了很多时间!