在一个进程里加载一个DLL后,DLL里面进行了多个new操作,然后把返回的地址放在进程的某个结构里面保存,可是后来当把DLL卸掉后,用delete来删除该结构里面的指针要出错.DLL被卸载后这些地址怎么会失效了?难道是DLL使用的堆是自己新建的堆而不是使用进程的默认堆吗?

解决方案 »

  1.   

    堆是进程相关的. 跟DLL没关系
      

  2.   

    是DLL自己的堆。所以不能进行跨模块删除内存(即使DLL没有被卸载也不行)使用MFC的共同DLL的除外-----因为使用MFC的话,所有new和delete实际上都是发生在MFC42.DLL中的,就没有跨模块的问题了。
      

  3.   

    ??...怎么两位的意见不一致啊?如果是DLL自己的堆的话,那是不是对所有的DLL都是这样:DLL里面进行的堆操作都不是使用加载进程的堆,而是自己新建堆.
    另外既然是在同一个进程的地址空间里,又为什么不能跨模块删除内存呢?为什么要采用这个机制呢,是为了模块的保护吗?
      

  4.   

    new 和 delete实际上会最终调用HeapAlloc和HeapFree的。你可以在MSDN上看看这两个函数的说明。里面有一个hHeap的参数,你可以卡看看malloc的最终调用 :
      return HeapAlloc( _crtheap, 0, size );
    这里的_crtheap在每个DLL模块中都会有的,这样就说明每个模块的内存段实际上是自己管理的。这样你如果在其他模块中free了,由于_crtheap值不同,所以不能free其他模块的内存。
      

  5.   

    我试了. 确实不行, 不好意思
    ---------------------------
    Microsoft Visual C++ Debug Library
    ---------------------------
    Debug Assertion Failed!Program: E:\PROC\KRH\VC\SDK\HeapTest\debug\HeapTestExe.exe
    File: dbgheap.c
    Line: 1044Expression: _CrtIsValidHeapPointer(pUserData)For information on how your program can cause an assertion
    failure, see the Visual C++ documentation on asserts.(Press Retry to debug the application)
    ---------------------------
    终止(A)   重试(R)   忽略(I)   
    ---------------------------
      

  6.   

    呵呵,多谢各位指点.在<<windows核心编程>>的P465页讲了这个情况:原因是加载进程和DLL都链接到静态的c/c++运行期库,这样的话在这个进程的地址空间中存在两个不同的c/c++运行期库.这样的话由DLL分配的堆内存和进程的堆就不是同一个堆了.但是如果是这样的话,是不是进程和模块的堆都是在c/c++运行期库中分配的堆呢,进程的默认堆呢?继续学习,也请各位发表一下意见.
      

  7.   

    如果exe和dll都动态link到crt,应该是用的同一个堆
      

  8.   

    如果不能正确free,那肯定是HeapFree的时候,其堆句柄不同造成的,也就是应该是2个不同的堆.
    个人意见.期望高手做出正确解答.
      

  9.   

    不同的,DLL里new出来的内存,不能在外面delete