DLL和exe里的malloc和free不能混用的问题

DLL和exe里的malloc和free不能混用的问题
2010年12月26日
  今天老玉米提了一个问题问为什么dll里malloc的内存如果在exe里free的话会出错,我分析了一下C库的原代码,得出结论如下:
  刚看了一下malloc和free 的源代码,在这两个函数中都有对全局变量的引用,而malloc和free是C库函数,分别被静态链接到exe和dll里,这样他们引用的全局变量也会有两份各是各的,自然不能混用。
  GlobalAlloc之类的windows API函数应该行。
  茶壶贴了一贴,说dll因为有自已的堆栈所以不能混用,我表示怀疑,继续看源代码,找到支持上面结论的真正原因:
  DLL是否有自已的堆栈我不知道, 但dll和exe里的malloc和free不能混用的真正原因就是我上面说的,有源代码为证,
  malloc 里真正分配的是这一句,见malloc.c里
  return HeapAlloc( _crtheap, 0, size );
  _crtheap是个全局变量,在_heap_init这个函数里初始化,见heapinit.c:
  // Initialize the "big-block" heap first.
  if ( (_crtheap = HeapCreate( mtflag ? 0 : HEAP_NO_SERIALIZE, BYTES_PER_PAGE, 0 )) == NULL )
  return 0;
  而_heap_init 在wWinMainCRTStartup 这个函数里调用(见crt0.c),同时也会在_DllMainCRTStartup里调用(见dllcrt0.c )。而winmain和dllmain 分别在wWinMainCRTStartup 和DllMainCRTStartup里调用,但都在调用了_heap_init之后(事实上是DllMainCRTStartup调用了_CRT_INIT之后才会调用用户的dllmain,而_CRT_INIT里调用了_heap_init这也就是说至少_crtheap这个变量在dll和exe里会各有一份,这才是dll和exe里不能混用malloc和free的真正原因。
  如果使用LoadLibraryEx装入dll,并指定DONT_RESOLVE_DLL_REFERENCES参数来让系统不调用用户的dllmain,dll和exe的malloc和free仍然不能混用,因为即使指定了DONT_RESOLVE_DLL_REFERENCES参数DllMainCRTStartup里仍会调用_CRT_INIT来初始化自已的_crtheap。
  [补充]
  DLL中的内存分两类,一类是共享内存,一类是进程私有内存
  例如,进程P1和P2同时引用同一个DLL,一般情况下,DLL中声明的变量会在P1和P2的进程空间内产生各自的副本
  也就是说,DLL中的变量,对于各个进程是独立的
  某些情况下,有必要在DLL中产生一块共享内存,多个进程都访问到同一块数据,比如,某些设备驱动程序,需要内部保留一个设备忙/空闲之类的状态标志,这个标志就必须作为共享内存存在,保证只有一份
  对于DLL中分配的内存,我觉得本身没有什么神秘之处,Windows程序之下的内存分配,最终都需要通过OS来完成,老玉米的问题,很可能是象北京色狼说的那样,不是内存本身的问题,是内存管理程序的故障
  因为各种语言的RTL库中的内存管理程序,它本身也需要通过自己的内部数据来管理内存分配的状态
  在DLL中调用的内存管理程序和在EXE中调用的内存管理程序不是同一块,而且它们内部维护内存分配信息的数据也不是同一块,所以造成老玉米的问题
  如果上面的说法成立的话,那么,不要用C的RTL来申请和释放内存,直接通过Windows API来申请和释放内存,比如GlobalAlloc/GlobalFree/LocalAlloc/LocalFree/HeapAl loc/HeapFree等等,应该就不会有问题了
  老玉米快去测试,报告结果
  当然如果dll和exe的编写语言不同的话,更不能混用了,各种语言都会封装winAPI来实现自已的内存管理库函数。
  原文地址: http://bjwf.cndev.org/2004/06/03/559/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值