如果用了CRT的内存分配(new,delete,malloc,free,...),你的dll和exe是静态或动态连接CRT的时候必须一致。msvcrt.dll用了单独的一个heap的,跟你的静态连接crt时用的heap不相同。
project settings->c/c++->code generation->use runtime library->dll和exe选择要一致
project settings->c/c++->code generation->use runtime library->dll和exe选择要一致
解决方案 »
- 网络编程里面在FD_CLOSE这个消息里面的wparam代表什么着什么意思?
- TXT文件的操作
- C/S模式下 服务器怎么判断客服端是否已经断开
- 为什么用TCP协议传输大量数据时,并非每次传输8192字节?而是比这个8192要少。
- 改背景色的CEDIT中编辑时发现删除的字和重新输入的字都重叠在一起了,如何解决?
- 请问有人看过《COM原理与应用》(潘爱民)吗?第二章例子的问题。
- 请教一个CEdit问题
- 我用mfc建立一个应用程序,运行的程序标题显示为:无标题**,在哪可以去掉这个无标
- 如何将HTML格式的内容转换成纯TEXT格式,反之又如何做?
- 求助:vc和matlab混合编程
- 编译一个系统级的DLL需要怎样指定DEF文件何编译参数?
- 有谁知道163帐号可不可以漫游和怎样漫游?
从 DLL 导出一个释放内存的函数,在 EXE 里面凡是从 DLL 分配的内存都用它释放。
最好在你的DLLMAIN 里去释放它。 如果想要实现数据共享的话 ,用内存CreatFileMapping
或者用 #pragma data_("Shared")
volatile You_value
#pragma data_seg()
#pragma comment (Linker,"/Sectioin:Shared,RWS")
case DLL_PROCESS_DETACH:两种情况分别处理了dll创建和摧毁,可以在此时分配内存和释放内存。在Exe中释放dll的内存,如果该dll还有用,释放掉它的内存合理吗?
你结论的后半句说得不对,对不同的进程而言内存指针不能互用,但EXE和加载的DLL同属于一个进程,是少数(唯一?)可以互用的例子。
ciba:“在Exe中释放dll的内存,如果该dll还有用,释放掉它的内存合理吗?”
当然不行!但这里问题不是这种情况。这里的问题是"如果该dll不再使用,释放掉它的内存合理,但为什么失败?"
kylewu:"总之这种方法就是不规范"
太武断了,这种机制没什么不规范的,但之所以出问题是实现不规范!
其他各位:你们的回答多多少少,局部或全部的,不能令人信服或由此产生怀疑。可能是本人孤陋寡闻,请出示试验证据或来源出处(如bugn的多heap说),我们也好互相纠正,共同学习。
我同意bugn的 “如果用了CRT的内存分配(new,delete,malloc,free,...),你的dll和exe是静态或动态连接CRT的时候必须一致。”
失败可能因为,1)EXE和DLL中的new/delete在其中一处(EXE/DLL)被重载过,另一处(DLL/EXE)没有,2)或是因为bugn的多heap说(等待进一步证实),不管哪一种,下面的解法都一样。
即:如果你用了new/delete的话,请改成用::new/::delete(全局-未重载的-操作符)。
对于这种问题,我一般的解决办法是这样的:dll输出类的new和delete运算符,这样无论你在那里调用都行(任意模块),都是在执行原来dll的malloc,确保用的是同样的heap。示例:
#ifdef BUGN_EXPORT
#define BUGN_API __declspec(dllexport)
#else
#define BUGN_API __declspec(dllimport)
#endif
class CFoo{
public
BUGN_API void* operator new(size_t size) {return ::new char[size];}
BUGN_API void operator delete(void* p) {::delete p;}
}
你写的很有新意不错不错
我开始也是用一个输出函数来做的
不如你高
newx(生命在于不动)
说得不错值,非常同意
Runtime Library的程序(比如VC++编出来的程序),还有一个C运行库自己管理的堆。
此外,每个程序或DLL都可以自己创建私有堆。多处理器系统中,还可能有MP堆。
ecore2遇到的这种错误,一般说来都是因为分配和释放没有在一个堆上。(因为
一般没有人会犯把GlobalAlloc()分配出来的内存用delete释放一类的错误的吧)
所以我想这可能与你的DLL和EXE,在链接C运行库时的方式有关。比如DLL是静态链接
C运行时库,而EXE是动态链接,那么在运行时,DLL内分配的内存一定是分在了C运行
时堆;而EXE在释放时则要进行一番查找来决定用哪个函数。vc++ v6.0运行库既可以
使用其自己内部的堆管理函数,也可以直接调用操作系统的堆管理函数(heapalloc()
系列的函数)。如果是运行于nt或2000,则用heapalloc();否则检查环境变量
__global_heap_selected,以决定是用heapalloc,vc6堆函数还是vc5堆函数;还决定
不了的话,会检查文件连接标志,如果是由vc++ v6或更高的版本创建的,就使用版本6
的堆函数,否则使用版本5的堆函数。
很多时候为了效率,还是需要用一些不太规范的方法,冒一些险。至于多heap的问题,大概就是bugn说的那样了,不过我补充一下,就是如果dll用静态连接msvcrt.dll,那么dll的初始化代码会另外分配一个crt heap,如果用动态连接,就会用process原来的crt heap,exe的情况也一样。如果dll静态连接msvcrt.dll,就会有两个crt heap,那么dll中malloc的内存块对于exe的heap来说是非法的。这可以在CRTDLL.C和DLLCRT0.C里面看到其中的差别。因此并不能保证在dll中分配的内存在exe中能正确的释放。我们写dll的目的之一就是代码重用,这种方法不能保证别的exe能不能正确的使用dll的资源,所以我认为这种方法不规范,如果是作为大项目的开发,这种方式不可取。因为其他程序员可能不清楚其中潜在的问题,很容易造成程序的不稳定。我还是比较偏向于使用IMalloc的,可能写COM比较多的关系吧。如果不是特别频繁的分配/释放,IMalloc基本上不会造成明显的效率下降。至于频繁的分配/释放,还不如一开始开个缓冲区,减少分配/释放?