是什么让它很难找到?你是如何追踪它的?
不够紧密闭合,但是也见
/sf/ask/17360801/
一台jpeg解析器,在监控摄像机上运行,每次公司首席执行官进入房间时都会崩溃.
100%可重现的错误.
我没骗你!
这就是为什么:
对于那些对JPEG压缩知之甚少的人来说 - 图像被分解成一个小块矩阵,然后使用魔法等进行编码.
当首席执行官进入房间时解析器会窒息,因为他总是有一个方形图案的衬衫,这引发了一些特殊情况的对比和块边界算法.
真正的经典.
这不会发生在我身上,但是一位朋友告诉我这件事.
他不得不调试一个很少崩溃的应用程序.它只会在周三 - 9月 - 9日之后失败.是的,一年中的362天,一切都很好,一年中有三天会立即崩溃.
它会将日期格式设置为"2008年9月22日星期三",但缓冲区是一个字符太短 - 所以当你在一个月中拥有最长名称的2位数DOM时,它只会导致问题最长的名字.
这需要了解一些Z-8000汇编程序,我将在后面解释.
我正在研究嵌入式系统(在Z-8000汇编程序中).公司的另一个部门是在同一平台上构建一个不同的系统,并编写了一个函数库,我也在我的项目中使用它.错误是每次我调用一个函数时,程序崩溃了.我检查了所有的输入; 他们很好.它必须是图书馆中的一个错误 - 除了图书馆已在全国数千个POS网站中使用(并且工作正常).
现在,Z-8000 CPU有16个16位寄存器,R0,R1,R2 ...... R15,它们也可以作为8个32位寄存器寻址,命名为RR0,RR2,RR4..RR14等.该库已写入从头开始,重构一堆旧库.它非常干净,遵循严格的编程标准.在每个函数的开头,将函数中使用的每个寄存器压入堆栈以保留其值.一切都干净整洁 - 它们很完美.
然而,我研究了库的汇编列表,我注意到该函数有些奇怪 - 在函数的开头,它有PUSH RR0/PUSH RR2,最后有POP RR2/POP R0.现在,如果你没有遵循这一点,它会在开始时在堆栈上推送4个值,但最后只删除其中的3个值.这是灾难的秘诀.堆栈顶部有一个未知值,需要返回地址.该功能无法工作.
除了,我可以提醒你,它正在工作.它在成千上万台机器上被称为每天数千次.它不可能不起作用.
经过一段时间的调试(在使用80年代中期的工具的嵌入式系统上的汇编程序中并不容易),它总是会在返回时崩溃,因为坏的值是将它发送到随机地址.显然我必须调试工作应用程序,找出它没有失败的原因.
好吧,请记住,库非常适合保留寄存器中的值,所以一旦你将一个值放入寄存器,它就会保留在那里.R1里面有0000.调用该函数时,它总是有0000.因此,该错误将0000留在堆栈上.因此,当函数返回时,它将跳转到地址0000,这恰好是一个RET,它将从堆栈中弹出下一个值(正确的返回地址),然后跳转到该地址.数据完美地掩盖了这个bug.
当然,在我的应用程序中,我在R1中有不同的值,所以它只是崩溃....
这是在Linux上,但几乎可以在任何操作系统上发生.现在大多数人可能都熟悉BSD套接字API.我们年复一年地愉快地使用它,并且它工作.
我们正在开发一个可以打开许多套接字的大规模并行应用程序.为了测试它的操作,我们有一个测试团队,可以打开数百个,有时超过一千个连接进行数据传输.使用最高频道号码,我们的应用程序将开始显示奇怪的行为.有时它只是崩溃了.另一次我们得到的错误根本不可能是真的(例如,accept()在后续调用中返回相同的文件描述符,这当然会导致混乱.)
我们可以在日志文件中看到出现问题,但很难确定.使用Rational Purify进行的测试表明没有错.但有些事情是错的.我们在这方面工作了好几天,并且越来越感到沮丧.它是一个showblocker,因为已经协商的测试会在应用程序中造成破坏.
由于错误只发生在高负载情况下,我仔细检查了我们对套接字所做的一切.我们从未测试过Purify中的高负载情况,因为在这种内存密集的情况下它是不可行的.
最后(幸运的是)我记得大量的套接字可能是select()的问题,它等待套接字上的状态变化(可能读/可写/错误).我们的应用程序确实在它到达带有描述符1025的套接字的那一刻就开始肆虐.问题是select()与位字段参数一起工作.位字段由宏FD_SET()和朋友填写,不要检查它们的参数是否有效.
因此,每当我们获得超过1024个描述符(每个操作系统都有自己的限制,Linux vanilla内核有1024个,实际值定义为FD_SETSIZE)时,FD_SET宏会愉快地覆盖其位字段并将垃圾写入内存中的下一个结构.
我用poll()替换了所有select()调用,这是一个精心设计的替代arcane select()调用,而高负载情况从来就不是问题.我们很幸运,因为所有套接字处理都在一个框架类中,15分钟的工作可以解决问题.如果select()调用遍布整个代码,情况会更糟.
得到教训:
即使API函数已有25年历史且每个人都使用它,它也可能有一个你还不知道的黑暗角落
API宏中未经检查的内存写入是EVIL
像Purify这样的调试工具对所有情况都无济于事,特别是在使用大量内存时
如果可能,始终为您的应用程序提供框架.使用它不仅可以提高可移植性,还可以在API错误的情况下提供帮助
许多应用程序使用select()而不考虑套接字限制.所以我很确定你可以通过简单地使用许多套接字来导致许多流行软件中的错误.值得庆幸的是,大多数应用程序永远不会超过1024个套接字.
操作系统开发人员不喜欢安全的API,而是将责任归咎于开发人员.Linux select()手册页说
"如果描述符值小于零或大于或等于FD_SETSIZE,则这些宏的行为是未定义的,FD_SETSIZE通常至少等于系统支持的最大描述符数."
那是误导.Linux可以打开超过1024个套接字.并且行为绝对定义明确:使用意外值会破坏正在运行的应用程序.开发人员只是覆盖其他结构,而不是让宏对非法值有弹性.FD_SET在linux头文件中实现为内联汇编(!),并将评估为单个汇编器写入指令.没有丝毫限制检查发生在任何地方.
要测试您自己的应用程序,您可以通过在main()之后直接以编程方式打开FD_SETSIZE文件或套接字然后运行应用程序来人为地夸大使用的描述符数量.
Thorsten79
我是一个硬件问题......
回到当天,我使用了带有21英寸CRT显示器的DEC VaxStation.我们搬到了新大楼的实验室,并在房间的对角安装了两个VaxStation.上电后,我的显示器像迪斯科舞厅一样闪烁(是的,这是80年代),但另一台显示器没有.
好的,换掉显示器.另一台显示器(现在连接到我的VaxStation)闪烁,我的前显示器(移动到房间)没有.
我记得基于CRT的显示器对磁场很敏感.实际上,它们对于60Hz的交变磁场是非常可接受的.我立刻怀疑我工作区域的某些东西产生了60赫兹的改变磁场.
起初,我怀疑在我的工作区域.不幸的是,即使关闭所有其他设备并拔下电源插头,显示器仍然会闪烁.那时,我开始怀疑建筑物里有什么东西.
为了测试这一理论,我们将VaxStation及其85磅显示器转换为便携式系统.我们将整个系统放在滚动推车上,并将其连接到100英尺的橙色结构延长线上.计划是将此设置用作便携式场强计,以便找到有问题的设备.
滚动显示器让我们完全糊涂了.显示器正好在房间的一半闪烁,但不是另一边.房间呈正方形,门对面的角落,显示器在连接门的诊断线的一侧闪烁,但不在另一侧.房间四面环绕着走廊.我们将显示器推入走廊,闪烁停止了.事实上,我们发现闪烁只发生在房间的一个三角形的一半,而不是其他地方.
经过一段时间的混乱,我记得房间有一个双向天花板照明系统,每扇门都有电灯开关.那一刻,我意识到出了什么问题.
我把显示器移到房间的一半有问题,然后关掉天花板灯.闪烁停止了.当我打开灯时,闪烁恢复.从任一灯开关打开或关闭灯,在房间的一半内打开或关闭闪烁.
这个问题是由于有人在连接天花板灯时偷工减料造成的.在照明电路上连接双向开关时,在SPDT开关触点之间连接一根导线,从一个开关上的公共线穿过灯,然后到另一个开关上的公共端.
通常,这些电线是并排在一起的.它们从一个开关盒中作为一组离开,运行到顶部天花板固定装置,然后运行到另一个盒子上.关键的想法是,所有载流导线都是并排在一起的.
当建筑物接线时,开关和灯之间的单线穿过天花板,但是在开关之间行进的电线穿过墙壁.
如果所有导线彼此靠近并且彼此平行,那么由一根导线中的电流产生的磁场被附近导线中的相等和相反电流产生的磁场抵消.不幸的是,灯的实际接线方式意味着房间的一半基本上位于大型单匝变压器初级线圈内.当灯亮起时,电流在一个环路中流动,而不良的监视器基本上位于一个大型电磁铁内.
故事的道德:交流电源线中的热线和中性线彼此相邻是有充分理由的.
现在,我所要做的就是向管理层解释为什么他们必须重新布线部分新建筑......
你遇到一些代码的错误,经过研究,你得出结论:"这种方法根本不可行!" 突然它停止工作,虽然它总是以前工作.
我在工作中帮助构建的产品之一是在客户站点上运行了几个月,收集并愉快地将收到的每个事件记录到SQL Server数据库中.它运行了大约6个月,收集了大约3500万条左右的记录.
然后有一天,我们的客户问我们为什么数据库近两周没有更新.经过进一步调查,我们发现正在进行插入的数据库连接无法从ODBC调用返回.值得庆幸的是,执行录制的线程与其余线程分开,允许除录制线程之外的所有内容继续正常运行近两周!
我们尝试了几个星期,以便在除此之外的任何机器上重现问题.我们永远无法重现这个问题.不幸的是,我们的其他几个产品然后以相同的方式开始失败,其中没有一个将其数据库线程与其余功能分开,导致整个应用程序挂起,然后必须每次手动重新启动坠毁.
几周的调查变成了几个月,我们仍然有相同的症状:在我们使用数据库的任何应用程序中完全ODBC死锁.到目前为止,我们的产品充斥着调试信息和方法,以确定哪里出了问题,甚至到了某些产品将检测到死锁,收集信息,向我们发送结果,然后重新启动自己的地方.
有一天在服务器上工作时,仍在从应用程序崩溃时收集调试信息,试图弄清楚发生了什么,服务器BSoD就在我身上.当服务器重新上线时,我在WinDbg中打开了minidump以找出违规驱动程序是什么.我得到了文件名并将其追溯到实际文件.在检查了文件中的版本信息后,我发现它是计算机上安装的McAfee防病毒套件的一部分.
我们禁用了防病毒软件,因此没有一个问题!
我只是想指出一个相当普遍和令人讨厌的错误,可能发生在这个谷歌区域时间:
代码粘贴和臭名昭着的减去
那时你复制粘贴一些带有减号的代码,而不是常规的ASCII字符连字符 - 减号(' - ').
另外,减去(U + 2212),连字符 - 减号(U + 002D)
现在,即使减号在某些编辑器(或DOS shell窗口)上被假定为长于连字符减号,根据所使用的字符集,它实际上呈现为常规的' - '连字符 - 减号.
而且......你可以花几个小时试图找出这个代码无法编译的原因,逐一删除每一行,直到找到真正的原因!
可能不是那里最棘手的错误,但足够令人沮丧;)
(感谢ShreevatsaR在原始帖子中发现反转 - 请参阅评论)
首先是我们发布的产品出现了一个错误,但是当我尝试调试问题时,它没有发生.我一开始认为这是一个"发布与调试"的东西 - 但即使我在发布模式下编译代码,我也无法重现这个问题.我去看看是否有其他开发人员可以重现这个问题.不.经过对程序输出的大量调查(产生混合汇编代码/ C代码列表)并逐步完成已发布产品的汇编代码(哎呀!),我找到了违规行.但这条线对我来说很好看!然后,我必须查找汇编指令的作用 - 并且确定已发布的可执行文件中的错误汇编指令.然后我检查了我的构建环境生成的可执行文件 - 它有正确的汇编指令.事实证明,构建机器以某种方式损坏并且仅为该应用程序的一条指令产生了坏的汇编代码.其他所有内容(包括我们产品的早期版本)都会向其他开发人员机器生成相同的代码.在向软件经理展示我的研究成果后,我们迅速重建了我们的构建机器.
在网络应用程序的深处某处是线(简化):
if (socket = accept() == 0) return false; //code using the socket()
通话成功后发生了什么?socket
设置为1. send()
给1时做什么?(例如:
send(socket, "mystring", 7);
它打印到stdout
...这是我发现4小时后想知道为什么,我printf()
的所有s被取出后,我的应用程序打印到终端窗口而不是通过网络发送数据.
对于80年代的数据通用小型机上的FORTRAN,我们遇到了一种情况,即编译器导致常数1(一)被视为0(零).之所以发生这种情况是因为一些旧代码将值1的常量传递给一个函数,该函数将该变量声明为FORTRAN参数,这意味着它(应该是)不可变的.由于代码中的缺陷,我们对参数变量进行了赋值,并且编译器兴高采烈地将其用于常量1到0的内存位置中的数据更改.
许多不相关的函数后来我们有代码与文字值1进行比较,测试将失败.我记得在调试器中查看代码的时间最长.我打印出变量的值,它将是1但测试'if(foo .EQ.1)'将失败.我花了很长时间才想要让调试器打印出它认为1的值是什么.然后它花费了大量的头发来追溯代码以找到常数1变为0的时间.
不是很强硬,但是当它被发现时我笑了很多.
当我为在线商店维护一个24/7订单处理系统时,一位客户抱怨他的订单被"截断"了.他声称,虽然他所下的命令实际上包含了N个职位,但系统接受了更少的职位而没有任何警告.
在我们追踪订单流经系统后,揭示了以下事实.有一个存储过程负责在数据库中存储订单项.它接受了一个订单项列表作为字符串,它编码(product-id, quantity, price)
三元组列表,如下所示:
"<12345,3,19.99> <56452,1,8.99> <26586,2,12.99>"
现在,存储过程的作者太聪明了,无法使用普通的解析和循环.于是,他直接被替换转化串入SQL多插入语句"<"
与"insert into ... values ("
和">"
用");"
.如果只是他没有将结果字符串存储在varchar(8000)变量中,这一切都很好和花花公子!
发生了什么事情,他"insert ...; insert ...;"
被截断为第8000个字符,对于那个特定的顺序,剪切是"幸运的"足以在insert
s 之间发生,因此截断的SQL在语法上保持正确.
后来我发现sp的作者是我的老板.
我在控制台游戏中遇到了一个错误,只有在你战斗并赢得一场冗长的boss战之后才会发生,然后在5中只有大约1次.当它触发时,它会使硬件100%楔入并无法与外界对话一点都不
这是我见过的最害怕的虫子; 修改,自动化,检测或调试boss-battle会隐藏bug(当然我必须做10-20次运行来确定bug已隐藏).
最后我通过反复阅读代码2-3天发现了问题(缓存/ DMA /中断竞争的事情).
在测试我最近添加到交易应用程序的一些新功能时,我碰巧注意到显示某种交易结果的代码永远不会正常工作.在查看了源代码控制系统之后,很明显这个bug已经存在了至少一年,而且我很惊讶没有一个交易者曾经发现它.
在困惑了一段时间并与同事核实后,我修复了错误并继续测试我的新功能.大约3分钟后,我的电话响了.在另一端是一个愤怒的交易员谁抱怨他的一个交易没有正确显示.
经过进一步的调查,我意识到交易者已经被我在3分钟前的代码中注意到的完全相同的错误所击中.这个错误已经存在了一年,只是等待开发人员过来并发现它以便它可以实现真正的攻击.
这是一种被称为Schroedinbug的错误的好例子.虽然我们大多数人都听说过这些奇特的实体,但是当你在野外遇到一个实体时,这是一种令人毛骨悚然的感觉.
当我认为C++和数字手表非常整洁时,这又回来了......
我因能够解决困难的内存泄漏而享有声誉.另一支队伍发生了无法追查的漏洞.他们让我调查.
在这种情况下,它们是COM对象.在系统的核心是一个组件,它给出了许多曲折的小COM对象,它们看起来或多或少相同.每一个被交给了许多不同的客户,每一个负责执行AddRef()
和Release()
相同的次数.
没有办法自动计算谁调用了每个人AddRef
,以及他们是否有Release
d.
我在调试器中花了几天时间,在小纸片上写下十六进制地址.我的办公室满满的.最后我找到了罪魁祸首.向我求助的团队非常感激.
第二天我换成了GC语言.*
(*实际上并非如此,但对于这个故事来说将是一个很好的结局.)
Sun Microsystems的Bryan Cantrill就他使用他帮助开发的工具dtrace追踪的一个错误提供了一个出色的Google Tech Talk.
The Tech Talk很有趣,令人讨厌,内容丰富,令人印象深刻(很长,大约78分钟).
我不会在这里给出任何破坏者的错误,但他会在53:00左右开始揭露罪魁祸首.
想到的两个最棘手的错误都是在同一类型的软件中,只有一个在基于Web的版本中,一个在Windows版本中.
该产品是平面图查看器/编辑器.基于Web的版本有一个flash前端,可以将数据作为SVG加载.现在,这工作正常,只有有时浏览器会挂起.仅在几张图纸上,并且只有当你将鼠标摆动在绘图上一点时间时才会这样.我将问题缩小到单个绘图层,包含1.5 MB的SVG数据.如果我只采用了数据的子部分,任何子部分,则不会发生挂起.最终我突然意识到问题可能是文件中有几个不同的部分组合导致了这个bug.果然,在随机删除图层的各个部分并测试错误之后,我发现了令人讨厌的绘图语句组合.我在SVG生成器中编写了一个解决方法,修复了错误,但未更改动作脚本.
在Windows端的同一产品中,用Delphi编写,我们遇到了类似的问题.此处产品采用autocad DXF文件,将它们导入内部绘图格式,并在自定义绘图引擎中呈现它们.这个导入例程效率不高(它使用了很多子字符串复制),但它完成了工作.只有在这种情况下它不是.一个5兆字节的文件通常在20秒内导入,但在一个文件上耗时20分钟,因为内存占用量增加到1千兆字节或更多.起初它似乎是一个典型的内存泄漏,但内存泄漏工具报告它干净,手动代码检查也没有发现.问题原来是Delphi 5的内存分配器中的一个错误.在某些条件下,这个特定文件正在重新创建,它将容易出现严重的内存碎片.系统将继续尝试分配大字符串,并且无法将它们置于最高分配的内存块之上.集成新的内存分配库可以修复bug,而无需更改一行导入代码.
回想一下,最棘手的错误似乎是那些修复涉及改变系统的不同部分而不是发生问题的错误.
当客户的宠物小兔子通过以太网电缆中途啃咬.是.这不怎么样.
在设备调试器上有一个非常糟糕的平台上有一个错误.如果我们在代码中添加了printf,我们会在设备上崩溃.然后它会在与printf的位置不同的位置崩溃.如果我们移动了printf,崩溃将会移动或消失.事实上,如果我们通过重新排序一些简单的语句来改变代码,那么崩溃就会发生在与我们改变的代码无关的地方.
事实证明我们平台的重定位器中存在一个错误.重定位器初始化ZI部分并非零,而是使用重定位表来初始化值.所以每当重定位表在二进制文件中发生变化时,bug就会移动.所以简单地添加一个printf会改变重定位表的bug.
当我在一家电脑商店工作时,这发生在我身上.
有一天,有一位顾客来到商店,并告诉我们他的全新电脑在晚上和晚上工作正常,但在中午或早上根本不起作用.麻烦的是鼠标指针在那个时候不会移动.
我们做的第一件事是改变他的鼠标,但问题并没有解决.当然,两个老鼠都没有过错地在商店工作.
经过几次尝试,我们发现问题出在该特定品牌和鼠标型号上.客户工作站靠近一个非常大的窗户,在中午,鼠标在阳光直射下.它的塑料很薄,在这种情况下,它变得半透明,阳光防止光机械轮工作:|
我的团队继承了一个基于CGI的多线程C++ Web应用程序.主要平台是Windows; 一个遥远的二级平台是带有Posix线程的Solaris.出于某种原因,Solaris上的稳定性是一场灾难.我们有不同的人一年多来看这个问题,一直关闭(大部分是关闭),而我们的销售人员成功地推动了Windows版本.
症状是可怜的稳定性:各种各样的系统崩溃,几乎没有押韵或理由.该应用程序使用Corba和本土协议.一位开发人员甚至将整个Corba子系统删除作为一种绝望的措施:没有运气.
最后,一位资深的原创开发人员大肆想知道一个想法.我们查看了它并最终发现了问题:在Solaris上,有一个编译时(或运行时?)参数来调整可执行文件的堆栈大小.设置不正确:太小了.因此,应用程序耗尽了堆栈并打印了总红色鲱鱼的堆栈跟踪.
这是一场真正的噩梦.
得到教训:
头脑风暴,头脑风暴,头脑风暴
如果在不同的,被忽视的平台上出现问题,那么它可能是环境平台的一个属性
注意离开团队的开发人员转移的问题.如果可能,请以个人身份联系以前的人员以获取信息和背景信息.恳求,请求,达成协议.必须不惜一切代价尽量减少经验损失.
Adam Liss上面的消息谈到了我们所做的项目,让我想起了一个我必须处理的有趣错误.实际上,这不是一个错误,但我们将在一分钟内完成.
如果您还没有看到Adam消息,应用程序的执行摘要:销售人员自动化软件......在笔记本电脑上...他们拨打的一天结束...与母亲数据库同步.
一位用户抱怨说,每次他试图拨入时,应用程序都会崩溃.客户支持人员经历了所有他们通常的电话诊断技巧,他们什么都没找到.所以,他们不得不放弃到最终目标:让用户FedEx将笔记本电脑送到我们的办公室.(这是一个非常大的问题,因为每台笔记本电脑的本地数据库都是为用户定制的,因此必须准备一台新的笔记本电脑,运送给用户供我使用,同时我们处理他的原件,然后我们不得不换回来让他最终在第一台原始笔记本电脑上同步数据).
因此,当笔记本电脑到达时,我可以找出问题所在.现在,同步包括将电话线连接到内部调制解调器,转到我们应用的"通信"页面,然后从下拉列表中选择一个电话号码(预先选择使用的最后一个号码).DDL中的数字是定制的一部分,基本上是办公室的数量,以"+1"为前缀的办公室的数量,以及以"9 ,,,"为前缀的办公室的数量.从酒店等打电话
所以,我点击"COMM"图标,然后按回车键.它拨入,它连接到调制解调器 - 然后立即崩溃.我累了几次.100%的可重复性.
因此,在笔记本电脑和电话线之间挂起数据范围,并查看整个线路上的数据.它看起来很奇怪......最奇怪的部分是我能读懂它!
用户显然想用他的笔记本电脑拨入本地BBS系统,因此,更改应用程序的配置以使用BBS的电话号码而不是公司的电话号码.我们的应用程序期待我们的专有二进制协议 - 不长的ASCII文本流.缓冲区溢出 - KaBoom!
在他改变电话号码后立即开始拨号问题的事实可能会让普通用户知道这是问题的原因,但是这个家伙从未提及过.
我修复了电话号码,并将其发回给支持团队,并附上一张纸条,选择了"本周的骨头用户".(*)
(*)OkOkOk ......这个家伙的孩子真的发生了很大的机会,看到他的父亲每晚都拨打电话,想到你也是如何拨打BBS的,并在他独自回家的时候更改了电话号码用笔记本电脑.当它崩溃时,他不想承认他触摸了笔记本电脑,更不用说打破了它; 所以他就把它拿走了,并没有告诉任何人.
这是在我的毕业论文中.我正在编写一个程序,用FORTRAN模拟高强度激光对氦原子的影响.
一次测试运行如下:
使用程序1计算初始量子态,大约2小时.
从第一步开始对数据进行主模拟,对于最简单的情况,大约需要20到50个小时.
然后用第三个程序分析输出,以获得有意义的值,如能量,tork,动量
这些应该总是不变的,但事实并非如此.他们做了各种奇怪的事情.
经过两周的调试后,我对日志记录进行了狂暴,并在模拟的每个步骤中记录了每个变量,包括常量.
这样我发现我写了一个数组的末尾,它改变了一个常数!
一位朋友说他曾经因为这样的错误改变了文字2.
我的第一个多线程程序出现僵局!
找到它非常困难,因为它发生在线程池中.有时池中的线程会死锁,但其他线程仍然可以工作.由于池的大小比需要的大得多,因此需要一两个星期才能注意到第一个症状:应用程序完全挂起.
我花了几个小时来调试一些最终可以修复的东西,只有几个字符.
一些不同的例子:
当流中的裁剪值实际上完全有效时,ffmpeg有这种令人讨厌的习惯,即产生关于"脑热切割"的警告(指的是流内裁剪值> = 16的情况).我通过添加三个字符来修复它:"h->".
x264有一个错误,在极少数情况下(一百万帧中的一个)有某些选项会产生一个完全错误颜色的随机块.我通过在代码中的两个位置添加字母"O"来修复错误.原来我在早先的提交中拼错了#define的名字.
我的第一份"真正的"工作是为一家编写客户 - 服务器销售人员自动化软件的公司工作.我们的客户在他们的(15磅)笔记本电脑上运行客户端应用程序,并在一天结束时拨打我们的unix服务器以与Mother数据库同步.在一系列投诉之后,我们发现在认证过程中,一开始就有一个天文数字的呼叫在下降.
经过数周的调试后,我们发现如果传入呼叫由服务器上的getty进程应答,那么身份验证总是失败,该服务器的进程ID包含一个偶数,紧接着是9.结果验证是依赖于一个自制程序PID的8字符串表示; 一个错误导致一个违规的PID崩溃getty,后者用一个新的PID重新生成.第二次或第三次呼叫通常会找到一个可接受的PID,并且自动重拨使得客户无需进行干预,因此在电话账单到月底之前不会被视为重大问题.
"修复"(ahem)是将PID转换为表示八进制而不是十进制的值的字符串,这使得无法包含9并且无法解决根本问题.
基本上,涉及线程的任何事情.
我曾在一家公司担任过一个职位,在那里我有一个可疑的区别,就是成为唯一能够通过线程调试讨厌问题的人之一.惊恐的事件.在允许编写线程代码之前,您必须获得某种认证.
我在高中时听说过一个经典的虫子; 如果你坐在前面的椅子上,你只能登录的终端.(如果你站着,它会拒绝你的密码.)
它对大多数人来说非常可靠; 你可以坐在椅子上,登录,退出......但如果你站起来,你每次都会被拒绝.
最后,事实证明有些混蛋更换了键盘上的几个相邻按键,E/R和C/V IIRC,当你坐下时,你触摸键入并进入,但是当你站着时,你必须去打猎啄,所以你看了不起标签,但失败了.