[原]很多时候, 错误源于自己

很多时候, 错误源于自身, 因此当觉得什么地方不对了, 认为是别人的错误之前, 还是先在自己这里找找原因吧...

做了近一周的***(名字略去)集成, 单独用测试程序跑了许多遍, 也没见有多大问题, 心里还挺美的, 结果今天集成到业务版本里连上中间件和EPG, 一切台死机的概率比不死的还高. 想着既然测试程序基本不死, 死机应该与中间件的调用有关, 或是某处资源冲突或不足, 顺着这个思路抓了十几个日志也没看出个所以然来. 后来还是在某个指针内容的异常处找到突破口, 本来初值应该为空的一个指针却不为空, 一路追寻下来发现又犯了一次memset时对指针sizeof了, 而不是指针指向的整个结构. 其实半年多之前就犯过一次这个错误, 当时加了打印发现memset恰好对一个结构中某个位置的成员没有置为0, 瞪着眼睛看了半天代码觉得像见鬼一样, 最后还是被小H一眼看出来的. 唉, 没长记性啊...

往往被折腾到筋疲力尽的一个bug, 最终的解决仅仅是在一两行代码之间... 记得大约一年前, 刚正式工作不久, 和一个同事一起解决一个抽取索引文件不全的问题, 乱麻一样的代码里折腾了近两周, 也不知道在我加入前那个同事已经折腾了多久, 最后还是我想了一个将中途结果保存文件的办法(当然也离不了在Elecard Tools的帮助下查看文件), 终于将问题定位到约100多行的代码内, 而最终的解决是那个熟悉代码的同事将其中的一行注掉! 还有一次是几个月前, 有人反馈seek后有时会卡住, 本以为绝对不可能的事情, 折腾半天还真给复现出来了, 经过按部就班地跟踪, 最后定位在一个200多行, 经过我精心撰写, 并多次逐行检验过的模块streamqueue里, 最终的解决方案也是注掉了其中的一行代码. 那行代码在reset时习惯性的将所有成员重置, 正是其中一个未加细致考虑的重置导致某些小概率条件下无法运转下去. 揪出这个bug的根源花了近一天时间, 花费时间较长的原因是这个bug不易重现, 重现bug的时间决定了二分查找定位bug所需的时间, 而解决bug的关键在于找到bug的根源所在. 哎, 又跑题了, 本来是要说bug经常是在自己的代码里呢, 怎么跑到bug都是修改一两行代码解决了呢, 再继续...

前两周搞darwin服务器播放, 也是测试程序基本没发现问题, 集成到业务版本中就没有声音了, 来回试了许多次, 确定是这么个规律, 完全同样的库, 链接到不同的程序就产生了不同的效果, 怎么也不觉着是自己的库有问题. 不过由于可以确定没有声音是同步造成的, 决定打印pts看一下, 这一打印吓了一跳, 音视频差值大了去了. 之前调试用的服务器版本比较老, 计算的pts打印出来感觉没问题, 调试完就把这个打印关了. 这回播的片子是用最新的服务器软件发的, 打印pts一观察才发现还有一个rtp time base计算时没有减去... 修改之后不管是测试程序还是业务版本就都有声音了...

还有一次最离谱的是几个月之前, 在深圳与R哥一起, 我负责播放模块, 他负责上层集成. 那天发现个问题是本地文件播放结束时中间件操作会卡住20秒(不多不少, 恰好20秒), 但播放IP流时没有这个问题. 本来觉着中间件卡住跟播放模块远远没有关系的, 不过碍于R哥的面子, 那天也正好比较闲, 还是决定跟一下这个问题. 跟来跟去发现中间件在绘制一个图标时卡住了, 但绘制图标怎么能卡住呢, 跟进图形模块发现里面有绘制后等待成功的操作(绘制成功后会收到一个回调, 5秒超时), 这个等待有4次, 加起来恰好是20秒!!! 但为什么会等待超时呢, 一般应该是立即收到的! 在一阵灵感中想起底层库是在一个线程中依次发送所有回调消息的, 而绘制图标的操作恰好是在底层发送PLAY2END回调时在消息发送线程中被辗转调用的, 当然永远都无法等到了, 那个消息还排在队列里等这个函数返回了再发呢!!! 根源还是在于实现文件播放模块是偷了下懒, 直接在PLAY2END回调中调用了上层的事件回调... 绕了一大圈, 根源其实还是在自己这里, 即使看起来是与自己多么不相关的一件事...
原文地址:https://www.cnblogs.com/techsunny/p/1530633.html