VC中“其原因可能是堆被损坏,这也说明*.exe中或它所加载的任何DLL中有bug”的分析

网上的讨论很多,这里整理总结一下存档备份。

原因分析

来自百度空间:DLL和exe里的malloc和free不能混用[hi.baidu.com/huhejun/item/988e41361d0a95c7392ffab5];

来自CSDN论坛:Dll分配的内存块,应用释放的问题

来自CSDN博文:VC运行时库/MD、/MDd、/MT、/MTd说明 - holybin的专栏

综合以上几个地方的讨论,给出一个总结分析:

1、首先是模块和进程的关系win32环境下,模块分为两种:进程内模块和进程外模块,前者共享进程的内存空间,比如许多在进程中加载的dll;后者与进程一样,独立运行,通常供其它进程调用(由引用计数之类的管理),进程外模块当然也包括dll。在后面的叙述中简化成进程(exe)和同等地位的模块(dll)。【至于进程与模块的详细关系,我整理了一篇:模块与进程的关系 - holybin的专栏

2、其次是在内存使用上,进程有堆,而线程有栈:一个进程(模块)一个堆,一个线程一个栈。由于一个进程必然有一个主线程,所以一个进程(模块)会有一个堆(用于new分配内存)和一个栈(用于局部变量)与之绑定,这两个的大小都可以通过编译器选项指定。所以exedll应该拥有不同的堆内存,使得在其中一个那里申请的内存,不能在另一个那里释放(在哪借东西就在哪里还对吧)。

3、最后最重要的是,C运行时库(Cruntime libraryCRT是静态连接的。CRT不是使用进程缺省的堆来实现mallocnew中调用malloc)的,而是使用一个全局句柄 HANDLE _crtheap来分配内存的,这个_crtheap是在XXXCRTStartUpCRT提供的进口点函数)中创建的。 由于CRT静态连接,所以dll里有也会有CRT,因此也会有_crtheap。而在dll中的newmalloc)使用dll中的_crtheap句柄分配堆内存,在exe中的deletefree)中使用exe中的_crtheap释放堆内存,所以失败。


解决办法

1、使用单一的堆:分配内存把相应的new type[size]改为 HeapAlloc(GetProcessHeap(),0,size),释放内存时把相应的delete []p 改为HeapFree(GetProcessHeap(),0,p);或者用GlobalAlloc()代替new, 用GlobalFree()代替delete。

2、dll分配的内存由dll释放:在dll中输出一个函数给exe调用,专门用来释放由dll分配的内存。

综合(1)(2)两点,内存操作时不能混用malloc、new、free、delete等操作符和函数:

 

C

C++

Windows平台

COM

IMalloc接口

BSTR

申请

malloc()

new

GlobalAlloc()

CoTaskMemAlloc()

Alloc()

SysAllocString()

重新申请

realloc()

 

GlobalReAlloc()

CoTaskRealloc()

Realloc()

SysReAllocString()

释放

free()

delete

GlobalFree()

CoTaskMemFree()

Free()

SysFreeString()

以上这些函数必须要按类型配合使用(比如:new 申请的内存,则必须用 delete 释放;malloc申请的必须用free释放)。在 COM 内部,当然你可以随便使用任何类型的内存分配释放函数,但组件如果需要与客户进行内存的交互,则必须使用上表中的后三类函数族。IMalloc 接口又是对CoTaskXXX() 函数族的一个包装。包装后,同时增强了一些功能,比如:IMalloc::GetSize()可以取得尺寸,使用 IMallocSpy 可以监视内存的使用。

3、最简单的办法是修改项目属性中的“C运行时库”选项:项目属性—>配置属性—>C/C++—>代码生成—>运行时库,将Debug模式下的改成“多线程调试DLL(/MDd)”,或者将Release模式下的改成“多线程DLL(/MD)”。这样exe和dll就是使用同一个CRT(MSVCRT.DLL),就可以直接使用new和delete了。


再次编译运行时,可能会出现如下错误:fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD,表明需要设置共享DLL。

解决方案:“项目属性”—>“配置属性”—>“常规”—>“项目默认值”—>“MFC的使用”,选择“在共享 DLL 中使用 MFC”。


实际测试(出处不明)
测试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的设置不能随意修改。所以若有涉及到这种

问题的,最好的办法还是在哪个模块分配的就在哪个模块释放最好,要不然反倒会引来更多的麻烦。


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: vc90动态库是指Microsoft Visual Studio 2008所使用的动态链接库(DLL)。这些DLL文件是用于支持和运行使用VC++编写的应用程序的必要文件。在2008年的版本vc90动态库是指所需的用于运行VC++ 9.0版本的DLL文件。 vc90动态库vc 2008所需要的dll免安装.rar的意思是提供了用于2008年版的Visual Studio所需的vc90动态库的DLL文件的压缩文件,这些DLL文件可以免安装直接使用。 通常情况下,开发人员在创建VC++应用程序时,需要将所需的DLL文件打包到应用程序的文件夹,以确保应用程序能够正常运行。然而,如果vc90动态库vc 2008所需要的DLL文件已经被压缩到rar文件,并且可以免安装使用,那么开发人员可以通过直接解压文件并将DLL文件放置到应用程序的目录,而不需要进行繁琐的安装流程。 使用vc90动态库vc 2008所需要的DLL文件免安装.rar,开发人员可以更加方便地将这些DLL文件添加到他们的项目,确保应用程序的正确运行。这种方法适用于那些希望快速部署和交付应用程序的开发人员,而不需要进行繁琐的安装过程。 总而言之,vc90动态库vc 2008所需要的DLL文件免安装.rar提供了一种简便的方法,开发人员可以直接使用所需的DLL文件,而不需要进行繁琐的安装操作,以确保他们的VC++应用程序能够正确运行。 ### 回答2: vc90动态库是指用于Microsoft Visual Studio 2008的Visual C++ 9.0版本的动态链接库。这些动态链接库是用来实现C++程序的编译和运行所需的依赖库。通常情况下,在部署或者分享VC++ 2008程序时,需要将这些动态链接库dll文件打包并安装在用户的计算机上。 然而,有时候我们可能需要在没有安装VC++ 2008的计算机上运行程序,或者由于某些原因无法进行正常安装。在这种情况下,我们可以使用vc90动态库vc 2008所需要的dll免安装.rar文件来解决这个问题。 该rar文件包含了VC++ 2008所需的所有vc90动态库的dll文件。通过将这些dll文件解压到程序所在的目录即可实现程序的正常运行,而无需进行正式的安装。 需要注意的是,使用免安装dll文件的方法仅适用于特殊情况,并不推荐长期使用。正式环境下,应该按照正常的安装流程,将VC++ 2008动态库进行安装和配置。 综上所述,vc90动态库vc 2008所需要的dll免安装.rar文件提供了一种临时解决方案,用于在没有安装VC++ 2008或无法进行正常安装的情况下运行程序。使用方法是将rar文件dll文件解压到程序所在目录,以保证程序能够正常编译和运行。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值