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

时间:2021-08-01 13:07:34

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);比较暴力的方法。