很多时候你开发的软件奔溃了,来不及观察现象就跑飞闪退了,如何定位到有问题的代码是一个难题。
无法定位自己代码里错误的位置,这件事情本身很容易让程序员奔溃。地基里有一颗不知何时爆炸、无迹可寻的炸弹,在这基础上楼房盖的再高也是危房,是不能住人的。而程序员如果在自己的代码了埋了一个不知何时奔溃、无迹可寻的种子,那么他肯定会怀疑这个作品的意义,即使是整年的心血,也会有将它完整删除的冲动。
最近,在我开发的Qt桌面程序里,就遇到了一个很难定位的bug。具体表现为当我点击退出时,程序在相当长的一段时间里处于无响应状态,然后提醒程序异常结束。以往遇到程序异常结束,我会熟练地打开qtcreator的调试器,如果程序有异常抛出时,调试器会自动帮你定位到出错的代码。
然而这一次,我的软件有大量动态创建的对象,软件退出前会先销毁它们,而当打开调试器的时候,对象的销毁非常缓慢,需要30分钟的样子才能到达软件奔溃的位置,而且也不能保证奔溃每次都会出现,效率相当底下。[但我等(mei)得(ban)起(fa),所以我还是静静地等待了]
而更加让人无奈的是,当我把调试器好不容易定位到的错误代码修复、确定调试器下不会再奔溃后,关闭调试器再打开,软件退出时异常依然存在。
不用调试器观察bug就存在,观察了bug就不存在,我好像发现了不起的东西。。。
要打破这无奈的局面,我需要找到一个可以不借助调试器就可以观察异常堆栈的方法。印象里软件奔溃退出,唯一能记录程序执行状态的,应该就是核心转储dump了,就从这里入手。很快,我就找到了Qt捕获软件异常,并且生成转储文件的解决方案。
https://blog.csdn.net/taoerit/article/details/76297484blog.csdn.net有了转储文件,接下来就是寻找分析它的方法。在搜索引擎上一通操作下来,定位到了windbg神器。我安装的是windbg的全新版本,windbg preview(下载地址:https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools)。安装完直接双击便可以打开dump文件,输入!analyze -v,就可以自动分析出异常退出时候程序的运行堆栈情况。
从分析结果的第4行可以看出,程序的异常发生在QSGnode的destroy()函数调用以后,而我的程序里确实有几个类继承了QSGNode,如果我从它们的析构函数入手,或许就能定位错误的代码了。但仅仅从这些堆栈信息来定位错误位置依然是很艰辛,有没有可以直接告诉我出错的代码在哪一行的方法呢?
网上的帖子告诉我,结合PDB(Program DataBase)符号文件,windbg才能发挥出最大的魔力。然而非常不幸的是,我正在使用的MingW版本Qt无法生成pdb文件,我开始明白大家在说的MingW版本调试器很鸡肋,是怎么一回事了。[更新:一天visual studio的调试器体验下来,不管是加载速度,还是bug位置的定位、变量查看、运行时内存CPU占用情况,是全方位的香。qtcreator的debuger是什么垃。。。]
花了点时间重新安装VS2017版本的Qt,并且将工程迁移到VS2017版本,解决了一些兼容性问题,并根据下面链接的操作,确保软件可以正常生成PDB文件。
https://blog.csdn.net/qq_26374395/article/details/90313546blog.csdn.net到这一步的时候已经凌晨了,睡觉这件事情索然无味,让我愉快地再奔溃一次,生成如下的DUMP和PDB文件。
接下来在打开的windbg preview里,点击文件→settings→debugging settings,将Symbol path设设置成pdb文件所在的目录,点击OK。
一切准备就绪,回到windbg preview主页面,在command窗口输入!analyze -v,得到了以下的运行结果。
看到这里,哪里出错了,一目了然。。。简单分析得知,原来,软件退出的时候,Qt核心把rbw_ptr_自动delete了,并且没有设置成nullptr,导致LineNode访问到野指针了呀。
简单修改修改,软件正常退出的那一刻,睡意终于来袭了~~~
上面讲述了我使用Qt进行软件奔溃位置定位的方法,即使不是在Qt这个框架下开发,相信也有生成DUMP和PDB文件的方法的。发现了windbg之后,笔者发现自己对调试的技术还是很无知的,马不停蹄地买了本书,研究一下在软件调试方面还有什么我不知道的黑科技。
前段时间围观了写工业级别代码是怎样一种体验这个问题:写工业级别代码是怎样一种体验?
工业软件听起来遥不可及,其实一句永远不能奔溃就是他们最基础的要求了。所以一个写工业级别软件的人,手里的调试黑科技肯定不少吧。