本文介绍windows上崩溃分析的一些手段,顺便提多进程调试、死锁等。
1.崩溃分析过程
1.1 确认错误码
无论是用windbg还是用vs,首先应该注意的是错误码,而90%以上的崩溃都是非法访问。
在非法访问时,可以看一下访问的目标地址。地址是0,或者离0很近(0x00000008或0xfffffffc),
一般和空指针相关。如果是一个貌似正常的地址,一般是对象已析构后访问其数据,或者堆破坏。
1.2确认崩溃对应的C++操作
什么是确认崩溃对应的C++操作:
比如非法访问,通常得有个mov指令才会触发内存访问,然后导致崩溃。而mov指针对应于C++的哪一步呢?
比如a->b->c->foo();
在看到源码时,会定位于这一行,但是,并不清楚是哪一步访问失败。所以这个时候要查看对应汇编代码。
大概会有好几个mov,简单的分析就知道是哪一步时访问失败。
对编码的影响:
这就要求,不要在单个语句中写太复杂的东西比如
x ? b[i] : y > 0 ? c->member[8] : *ptr;
这样的代码崩溃,要还原到错误的地方很难。
虚函数调用:
通常
mov edx, dword ptr [ecx]
mov edx, dword ptr [edx+0x??]
call edx
意味着虚函数调用,每一行都可能是崩溃位置(在call内崩溃时,vs会标注出下一条语句的位置)。
在第一行崩溃意味着拿到一个非法指针,可能是空,也可以指向非法地址。
在第二行崩溃意味着对象已经析构,ecx指向可以访问,但是值不对,所以拿到的虚函数表不对。
在最后一行崩溃一般还有一个崩溃栈,但是看不到栈帧,在vs中对应的栈桢显示一个地址,没其它内容。
也一般意味着对象析构。
对象及析构函数:
析构函数是经常发生崩溃的地方,如果没有用户提供的析构函数,会定位到几行汇编。所以没事,就写个
析构函数吧,至少能定位到是析构函数。
在
1.崩溃分析过程
1.1 确认错误码
无论是用windbg还是用vs,首先应该注意的是错误码,而90%以上的崩溃都是非法访问。
在非法访问时,可以看一下访问的目标地址。地址是0,或者离0很近(0x00000008或0xfffffffc),
一般和空指针相关。如果是一个貌似正常的地址,一般是对象已析构后访问其数据,或者堆破坏。
1.2确认崩溃对应的C++操作
什么是确认崩溃对应的C++操作:
比如非法访问,通常得有个mov指令才会触发内存访问,然后导致崩溃。而mov指针对应于C++的哪一步呢?
比如a->b->c->foo();
在看到源码时,会定位于这一行,但是,并不清楚是哪一步访问失败。所以这个时候要查看对应汇编代码。
大概会有好几个mov,简单的分析就知道是哪一步时访问失败。
对编码的影响:
这就要求,不要在单个语句中写太复杂的东西比如
x ? b[i] : y > 0 ? c->member[8] : *ptr;
这样的代码崩溃,要还原到错误的地方很难。
虚函数调用:
通常
mov edx, dword ptr [ecx]
mov edx, dword ptr [edx+0x??]
call edx
意味着虚函数调用,每一行都可能是崩溃位置(在call内崩溃时,vs会标注出下一条语句的位置)。
在第一行崩溃意味着拿到一个非法指针,可能是空,也可以指向非法地址。
在第二行崩溃意味着对象已经析构,ecx指向可以访问,但是值不对,所以拿到的虚函数表不对。
在最后一行崩溃一般还有一个崩溃栈,但是看不到栈帧,在vs中对应的栈桢显示一个地址,没其它内容。
也一般意味着对象析构。
对象及析构函数:
析构函数是经常发生崩溃的地方,如果没有用户提供的析构函数,会定位到几行汇编。所以没事,就写个
析构函数吧,至少能定位到是析构函数。
在