您的位置:首页 > 其它

DLL函数中内存分配及释放的问题

2011-09-27 18:35 141 查看
DLL函数中内存分配及释放的问题

最近一直在写DLL,遇到了一些比较难缠的问题,不过目前基本都解决了。主要是一些内存分配引起问题,既有大家经常遇到的现象也有特殊的

情况,这里总结一下,做为资料。

错误现象是“其原因可能是堆被损坏,这也说明 **.exe 中或它所加载的任何 DLL 中有 bug

我的现象还有一个,就是直接运行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

以下是CSDN上的讨论,同样讨论的很详细了

以上是在网上找到的资料,今天做过详细测试,结果如下:

测试1:使用malloc/free组合来分配和释放内存,DLL中使用malloc分配,exe中使用free释放。

我建的是Win32 DLL工程, C/C++->Code generation 设置是 Multithread DLL debug, 但是exe工程设置是MultiThread debug,所以不管怎么样

,总是会抛异常. 这就间接证明了上述的描述是正确的, 若我修改exe工程设置是 MultiThread DLL debug, 那么malloc/free组合就能很好的工

作起来了。

测试2:使用HeapAlloc/HeapFree组合来分配和释放内存,DLL中使用HeapAlloc分配,exe中释放。

exe的配置还是MultiThread Debug,DLL中HeapAlloc(GetProcessheap(), HEAP_ZERO_MEMORY, 1024)分配,exe中HeapFree(GetProcessHeap(),

0, p)释放,,则还是无法正常运行,还是抛异常。若exe中设置成MultiThread DLL debug就正常运行了。

测试3:还是使用HeapAlloc/HeapFree来进行,但是DLL中导出一个方法来释放DLL中分配的内存。

若exe配置是MultiThread Debug,无法正常运行,抛异常。若修改成MultiThread DLL debug正常运行。

所以得到的结论如下:

不管是使用malloc/free组合还是HeapAlloc/HeapFree组合,exe工程均需要设置成MultiThread DLL debug才能正常运行起来的,CSDN上的那个

讨论在这儿貌似是由出入的,而且DLL的设置不能随意修改。所以若有涉及到这种问题的,最好的办法还是在哪个模块分配的就在哪个模块释放

最好,要不然反倒会引来更多的麻烦。

我在找“...其原因可能是堆被损坏,这也说明 **.exe 中或它所加载的任何 DLL 中有 bug。”解决办法的时候找到的,学到一点,呵呵。可

惜我那工程的直接原因并不是因为上面所说的(也许间接原因是),我的工程里是开启一个UI线程,UI线程中有一个view,结果单步调试时报错

“...其原因可能是堆被损坏,这也说明 **.exe 中或它所加载的任何 DLL 中有 bug。”,最后解决办法是,view需要用new创建,不能直接通

过create来创建,原因是view应该是建在堆上

以上是在网络上搜到的资料。我的实际情况又与这个有所不同,当然,我已经按照上述的方法都测试过了,没有解决问题。

我的问题是在线程里分配了(NEW)一个类的指针(一个包含套接字的类),但在程序退出时报这个错误。后来经过考虑,我发现可能是在程序

退出时,子线程仍在运行,造成指针仍在使用,所以我在退出时把子线程的循环条件置FALSE后,解决

随即又出现一个问题,我在程序退出时DELETE保存在LIST里的SOCKET的时仍然报这个错误。最后解决办法仍是上面的思路,(多线程)把程序

关闭时,先shutdown套接字,然后closesocket套接字,最后延时2秒,OK,取代了原来::WaitForSingleObject(hRecv,2000)然后再

TerminateThread(hRecv,temID);比较暴力的方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: