最近这三四天一直在跟一个bug做斗争:程序在运行过程中死掉,Output窗口显示:
1.Windows has triggered a breakpoint in ***, This may be due to a corruption of the heap...
2.Access violation reading location...
今天下午终于找到了真正的原因。那也就顺便把关于这个问题Google到的知识总结一下:
这些问题均有可能代表程序中出现了堆错误。
而出现堆错误的原因主要有 以下两大类:
首先是工程设置方面的问题:
1.在dll中申请的内存(new)在exe中释放了(delete),这时有可能会报堆错误;这时需要在dll中导出一个用于释放内存的函数;
2.在一个dll中申请的内存,在另一个dll中释放;而这两个dll使用的运行时库不同。这时可以如1一样确保哪个模块申请的内存就在那个模块释放,也可以将两个工程的运行时库设置成同一个,即MD(d)或者MT(d);
第二类是代码逻辑中的问题:
1.同一块地址的指针被释放(delete)了两次,会导致以上错误。一般地,在每次释放内存之后,都将相应指针设置为NULL,并在delete指针之前进行检查,可以避免这种问题;
2.内存申请之后,又对相应指针进行了改变,例如自增的(++)操作,使得指针没有指向内存块的首地址,也会出现这种错误。一般地,在申请到内存后需要指针运算的,拷贝一份指针变量进行运算,而原指针变量则保持不变。
我遇到的问题是属于第二类的第一种,但是涉及到了多线程的问题,比较隐蔽。具体是这样的:
有四个队列A1,A2,B1,B2,有两个线程需要通过一个类D的函数将A1,A2中的数据取出来,并复制一份,放入B1,B2。我在类D中定义了一个成员变量M用于临时存放A1,A2中的数据。当第一个线程将A1中数据赋给M之后,还没有将M放入B1之前,可能第二个线程就把M又赋成了A2中的数据。这样最后存放入B1,B2就是同一份数据,也就是两个指针指向了同一块内存。这样,在释放内存的时候,就会出现delete两次同一块内存的情况了。
这种情况下,给成员变量M加锁,或者使用两个成员变量分别对应两个线程,都可以解决这个问题。
欢迎转载,转载请注明出处http://ushertechblog.sinaapp.com/post-27.html