天天看点

unknown software exception(0x80000003)

    最近写的转换程序,在debug版下跑了9个小时,最终崩溃,直接弹出对话框说:

应用程序发生异常,unknown software exception(0x80000003),位置为0x10212ad0.

   又在IDE状态下debug版跑了16个小时,最终弹出用户断点对话框,点按钮后定位在 DBGHEAP.c 文件的第338行:

/* break into debugger at specific memory allocation */
if (lRequest == _crtBreakAlloc)
_CrtDbgBreak();      

lRequest == _crtBreakAlloc成立,lRequest =-1,其中,lRequest记录了当前内存分配次数,_crtBreakAlloc为用户设置的中断点(通过调用_CrtSetBreakAlloc进行设置),其初始值为-1L,即long型整数最大值。

   问题是:即使用户没有设置中断点,那么随着程序的运行其内存分配次数总会有达到最大值的那一刻。

  lRequest  初始化为_lRequestCurr,_crtBreakAlloc 初始化为-1,当程序启动时。每次 malloc(), lRequest (_lRequestCurr) 加1,经过一段时间运行后,lRequest (_lRequestCurr) 达到2,147,483,647。下一次再调用加1时则会数据溢出, 2,147,483,647 + 1 = -2,147,483,648,下次再加一则 lRequest (_lRequestCurr)从-2,147,483,648 加到 -1,这时_crtBreakAlloc 的值和lRequest (_lRequestCurr) 值都为-1,执行第二句 _CrtDbgBreak(),然后就出现用户设定断点提示,非IDE状态的debug版本则会直接报错崩溃。

   这说明我们的程序存在非常频繁的内存分配,可以考虑使用内存池以提高效率。

    解决办法有两个:

    1. 改用RELEASE版。事实证明,release版本下不会出现该错误。

    2. 少用malloc,new和delete动态分配内存;减少string和CString的使用,因为CString在内部实现中会调用new实现动态内存,想想啊,CString的字符串长度是可以任意变的,怎么会没有动态内存分配,又不可能每个CString都内置4G空间,对吧。(今天有看到帖子说,在debug版本中,cstring使用new和delete实现,但在release版本中小于512字节时使用4个不同大小的内存池实现,大于512字节时仍使用new和delete)

  下面给出一个最简单的测试用例:

#include <stdio.h>
int main()
{

int* i;
unsigned int j = 0;
while (1)
{
i = new int;
*i = 0;
j++;
delete i;
}

return 1;
}      

  本人今天(2008。12。25 WINXP SP2 VC6 SP6)在debug模式下跑了大概一两个小时后崩溃。崩溃断点就在

i =