今天在运行程序时,在释放内存的地方老是弹出堆被损坏。一直调试,都找不到原因。后来在网上搜索,总结了一下这个错误的原因。
出现这个错误的原因主要有两个:
(1) 同一块内存被释放了两次。
(2) DLL中分配的内存在EXE中释放。
同一块内存被释放两次,很好理解。
至于第二种情况,网上有一段很详细的解释:
一个模块一个堆,一个线程一个栈。
dll里malloc的内存,在exe里free会出错。
CRT(C运行时期库)不是使用进程缺省的堆来实现malloc(new中调用 malloc)的,而是使用一个全局句柄HANDLE _crtheap来分配内存的。这个 _crtheap是在XXXCRTStartUp(CRT提供的进口点函数)中创建的。
由于CRT静态连接,则楼主的DLL里有也有一个CRT,因此也有一个_crtheap。 而在dll中的new使用dll中的_crtheap句柄分配堆,在exe中的delete使用exe 中的_crtheap释放堆,当然失败!
解决办法:
1。在DLL中输出一个函数给EXE调用,专门用来释放由DLL分配的内存;
2。用GlobalAlloc()代替new,用GlobalFree()代替delete;
3。使用单一的堆,分配内存使用HeapAlloc(GetProcessHeap(),0,size) ,释放内存使用HeapFree(GetProcessHeap(),0,p);
4。把dll和exe的Settings的C/C++选项卡的Code Generation的Use Run-time liberary改成Debug Multithreaded DLL,在Release版本中 改成Multithreaded DLL;这样使用一个CRT了——MSVCRT.DLL。
以上提到的4中解决方法,采用任意一种就可以解决这个问题了。
再回到我遇到的问题,我报错的那个释放内存语句也是在EXE中释放DLL中分配的内存,但是我已经把项目属性设置成MDd里,按理说应该没什么问题了,但是运行仍然报错。后来实在没有办法了,只好修改代码,在DLL中分配内存,然后在DLL中释放内存。总算是解决了,但是真正的原因还是没有找到,看来等有时间的时候还是要在研究研究。