今天在CSDN的论坛里看到一个帖子,楼主询问崩溃问题如何调试. 我回复了一点点崩溃问题的调试经验,在略加整理之后形成了这篇BLOG.
1.假如怀疑跟通信量有关,可以人为的采用一些手段,产生巨大的通信量,从"偶尔崩溃"到"快速崩溃".从而能够在在线调试时复现这个问题, 这是最理想的情况. 有点让我想起来中国某位领袖说过的话,没有条件创造条件也要上.调试崩溃问题时,最怕不崩溃. 调过复杂系统的人都知道,运行一次不容易.
2.在线调试.运行一晚上不关机,到崩溃了调试器自然会捕获到异常.
如果Debug版本不崩溃,只是Release版本崩溃,那么有可能是编译器优化产生的问题.可以将优化选项去掉,看看是否仍然崩溃.如果去掉优化选项后不崩溃,那么基本上你倒霉了,需
要进一步尝试增减优化选项,直到发现是什么优化产生了问题,关掉此优化即可.
如果去掉优化后仍有问题,基本上可以肯定是你的代码有BUG.可以把Release版本配置成也产生必要的调试信息,再按照1或2的方式在线调试.
3.如果在线调试不崩溃,那只有实际运行了.编译时产生.MAP文件.使用SEH的__try .. __except语句捕捉异常. 要捕获内存访问方面的异常,恐怕还要加上捕捉异步异常的选项/EHa
了.
另外,在多线程应用中,必须在每个线程过程函数中包上SEH. 最后还需要在异常捕获后将发生异常时的CONTEXT用日志记录下来,主要是记录CPU执行到哪个地址上的指令时产生异常,以及指令正在访问的内存地址.这样通过MAP文件可以找到崩溃地址.我的另一篇BLOG介绍了一个利用MAP文件定位错误代码所在行号的工具DebuggerAide2008,可以在CSDN下载中心下载.
http://blog.csdn.net/robotom/archive/2007/04/04/1552345.aspx
4.崩溃地址其实只能作为参考,造成崩溃的真正凶手可能是之前的某个操作破坏了程序中的某个数据结构,而这个操作并没有使程序产生异常,直到后面的另一个操作要访问这个数据结构时,才引发异常,那么这个恐怕是比较难查了. 而且,这个破坏性操作可能与崩溃地址相隔很远,可能是在不同的线程中,或者不同的模块中,或者不同的DLL中。 这通常会让我非常郁闷.在经过N次的调试和执行之后,,也许能够从种种迹象,比如崩溃发生的条件和时机等等,发现一些蛛丝马迹.如果足够幸运,N次的静态阅读代码之后,也许还能找到若干处真正可疑的代码,最后经过排除,甚至能找到导致崩溃的真正的原因. 这种破坏性操作,可能是数组越界,也可能是对无效指针进行了写操作,而根据我的调试经验,在多线程程序中,后者似乎更常见些。 有很多调试工具可以帮助我们快速的找到这个破坏性操作! 比如Boundcheck,Rational Purify.我更推荐使用Rational Purify,因为它能在第一时间轻易的发现多种类型的破坏性操作。
发表于 @ 2007年05月10日 22:36:00|评论(loading...)|编辑