Memphis' Talk

拥抱社区, 记一次 Qt bug 的折腾过程

年初 Qt 发布了最新版本 5.8 的 Release 版本, 两天前我对自己的项目进行了版本升级, 遇到了莫名其妙的崩溃问题. 经过两天的瞎折腾之后, 仍然没有办法独立解决问题. 于是我向 Qt 社区发起了求助, 在 20 次浏览量, 15 个回复之后, 找到了问题的答案, 从此对 Qt 社区另眼相看. 趁热记录一下:

故事的开始

once upon a time …, 咳咳, 没有那么久, 就在几天前, 我更新了 Qt 5.8. 新版本的 Qt Creator 在打开速度和稳定性上都有了明显的提升. 于是开开心心地享用了一个早上. 然而你永远不知道明天和意外哪一个先来临, 当我将程序对接的服务器从本机切换到沙箱, 准备给同事更新一个新版本的时候, 它居然崩溃了… 于是开始了我对于这个问题的 Debug 之旅.

探索与发现

说时迟那时快, 我二话不说点击了 start Debuging 按钮. 程序顺利启动, 输入账号密码, 点击登录… 我了个擦嘞又崩溃了. 看来问题和这个登录请求有关.
这个时候我最正确的选择应该是打上断点, 开始单步调试找到程序崩溃的地方, 再仔细分析原因. 但是出于好奇和不理智, 我没有选择这个办法. 开始尝试通过现象来判断这个问题的原因.
于是我又切换回了本机服务器, 启动, 登录, 成功了. 看来问题出在选用的服务器上? 那么这 tmd 就很诡异了. 于是我开始分析两个服务器的不同之处:

  • 通过 curl 直接在命令行中对本机和沙箱服务器的登录接口进行访问, 都能够正常工作, 返回值也没有任何问题
  • 分析从本机和沙箱获得内容的编码, 也没有不同之处

时间就这样在反复的对比和尝试中流逝, 越着急越没有思路. 我的程序连最基本的登录功能都无法完成? 这 tmd 就很尴尬了呀.

神来的巧合

就在我焦头烂额查阅相关资料文档, 对比服务器差异时. 晴天一声炸雷!(并没有), 网络断了… 我的工作也随之被打断. 因为我连不上我的沙箱服务器.这一巧合触动了我, 是不是因为网络连接底层相关的代码, 导致了结果的不同? 带着这个疑问, 我开始了一个重要的尝试:
我将我访问的本机服务器 IP 地址从 127.0.0.1 改成了 192.168.1.103
看起来一个傻傻的异想天开的改动, 居然让我的程序再次崩溃了. 于是我开始思考这其中的奥秘, 前者是一个指代本机的 loopback 地址, 后者是我的网卡在局域网内的局域网地址. 粗略地看来, 从我本机上访问这两个地址的效果应该是约等于的, 但是其实有重要的差异. 对局域网内地址发起的请求要经过局域网网关, 能够被局域网的嗅探器嗅探到请求, 而对 loopback 地址是在网卡内部完成的, 外界对这些请求并不知情.

事已至此, 我终于能够小心翼翼地猜想. 这恐怕是 Qt 5.8 的一个官方 Bug!?

正轨

带着这个猜想, 我终于做了我最该做的事: step over 崩溃前后的代码. 望着程序一步一步走向 Qt 内部, 越来越确信这可能不是我的问题. 最终执行流程来到了汇编层.
我了个擦? 走到汇编了? 好办, Qt 不是开源的吗? 安装源码! 于是我开始陷入了另一个低效的大坑:

徒劳

根据 一去丶二三里查看和调试Qt源码 一文, 我开始配置我的 Creator, 然而博主使用的是 windows 版本进行介绍, 版本也和我的对不上号. 我甚至找不到在 IDE 中配置源码的选项. 这次尝试宣告失败.
又有传言说通过静态编译 Qt 源码, 能够达到调试到 Qt 内部的效果, 于是我开始了对 Qt 源码漫长的编译. 大概花了… 8 个小时… 可是由于个人的愚钝, 我还是失败了. 基本上这时候我开始陷入了怀疑人生的环节.

柳岸花明

直到这个故事的下半部分, 我才做了最应该做的事情: 向开源社区寻求帮助. 花了十多分钟, 我对这个 bug 做了一个最小规模重现. 贴到了 Qt 官方论坛上: Weird crash of QNetworkAccessManager::post()(由于众所周知的原因, 可能需要梯子), 短短的 20 次浏览量, 15 个回帖 (其中有一半还是我的), 这个问题就被确认了. QNetworkAccessManager 在 mac 系统上对于 proxy 的处理有问题! 只要主动 setProxy 为 NO_PROXY 就能够绕开这个 bug, 两天的蒙头苦干, 比不上一次简单愉快的谈话. 我终于可以和我的代码一起愉快地玩耍了.

回忆

这个故事告诉我们, 在电影院请不要大声喧哗!. 额当然不是这个, 虽然也很重要. 总结几点吧:

  • 查问题需要使用科学的步骤, 切忌用经验来回答
  • 站在深坑面前, 要正确地估量使用方法的代价. 比如时间开销, 还有对自己情绪的呵(nue)护(dai).
  • 站在真理面前要敢于质疑
  • 开源社区赛高!! 拥抱社区!!

啰嗦一句, 国外开源社区的小伙伴们真的超级热心肠, 不但积极帮忙讨论解决问题. 还对代码中可以改进的地方做出建议, 也会逗趣地对一些东西发出吐槽, 非常 nice.

好啦今天就唠叨到这里, 该去睡觉了, 拜个晚年祝路过的网友们鸡年大吉吧~ 科科~