关于极少出现的BUG怎么办?

刚才看了一篇文章是关于一种10000次才出现一次的BUG,用的是设置条件断点,用VC的话其实也可以直接调用Debug方面的API。

http://blog.csdn.net/ATField/archive/2009/08/28/4493003.aspx

 

但是,我有个问题,100000000次才出现一次的BUG怎么办?

 

别以为这是天方夜谭,在我的开发中,真真实实的出现过这种情况。当时具体作的项目记不大清了,不过这个问题是关于多线程,多公共变量的。我的任务是维护这个相当复杂的产品代码。

 

这个产品算是公司相当稳定的产品了,只有这个BUG很奇怪运行10几天后,会莫名其妙的死掉。当时找了很久都没有找到BUG,不得不用另外一个软件在10天重企一下这个服务。

 

不过我很幸运的找到了这个BUG.这个BUG的原因是多线程时 X++ 这个不是被编译器翻译成单条指令,而是三条指令(如下),并非原子性的,在极个别的情况下会出现其他线程访问冲突,读了错数据,导致后面越错越厉害,然后程序崩掉。

#include <windows.h>

int _stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR, int)
{
00401000  push        ebp 
00401001  mov         ebp,esp
00401003  push        ecx 
 int x = 0;
00401004  mov         dword ptr [x],0
 x++;
0040100B  mov         eax,dword ptr [x]
0040100E  add         eax,1
00401011  mov         dword ptr [x],eax

 return 0;
00401014  xor         eax,eax
}
00401016  mov         esp,ebp
00401018  pop         ebp 
00401019  ret         10h 

 

找到它的方法其实也很常见,就是在崩溃的地方察看调用堆栈,不仅是当前线程的调用堆栈,还有其他线程的调用堆栈,然后从头到尾把每个线程的流程好好分析一遍。最后,这个BUG的狐狸尾巴就露出来了。

 

其实,这个BUG就是一个变量没有加锁导致的,所以规范的代码是粉重要粉重要滴~

 

以下是这两个窗口的示例,线程窗口Thread显示当前进程所有的线程,调用堆栈Call Stack窗口显示该进程所有的函数。

大家也可以到http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx去下载符号,然后在VS里面设置路径,就可以显示出来ntdll的函数名称了,这样可以便于理解错误的原因。(我本来也可以显示的,自从装了SP2……还要重下个1G多的大包)

示例图片

 

 

 

保证这个数据安全还可以用volatile这个关键字标示这个数据,因为volatile在多线程的时候会告诉编译器把类似于X++这种语句优化翻译成一条指令(速度稍慢),但是它就是原子的了,就不会出这种问题了.

可惜的是,当时我们公司为了保证多线程的代码稳定和节约成本( 主要原因:'( ),Release版本是不允许开优化的(其实根本没有Debug版本),这样,volatile这个关键字加不加都一样了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值