zoukankan      html  css  js  c++  java
  • 【转载】Windows 下主程序与动态库(*.dll)释放对方分配的内存操作要点

    同样的代码程序:
    主程序中释放了一块在 动态库(*.dll)或共享库(*.so) 中分配的内存,
    Windows 将会出现程序崩溃,而 Linux 则正常运行。
     
    在 linux 下,每个进程只有一个 heap ,
    在任何一个共享库模块 *.so 中通过 new 或者 malloc 来分配内存的时候都是从这个唯一的 heap 中分配的,
    那么自然你在其它什么地方都可以释放。
     
    但是 windows 下面确不是如此:
    1. windows 允许一个进程中有多个 heap ,那么这样就需要指明一块内存要在哪个 heap 上分配,
       win32 的 HeapAlloc 函数就是这样设计的,
       给出一个 heap 的句柄、一个可选的分配操作标志、一个字节块大小,然后返回一个指针。
       每个进程都至少有一个主 heap ,它的句柄可以通过 GetProcessHeap 来获得,
       其它的堆句柄可以通过 GetProcessHeaps 取到。
       同样,内存释放的时候通过 HeapFree 来完成,还是需要指定一个堆句柄。
     
    2. 这样的设计显然是比较灵活的,
      但是问题在于这样的话,每次分配内存的时候就必须要显式的指定一个 heap 句柄,
       对于 crt 中的 new/malloc ,显然需要特殊处理。
       那么如何处理就取决于 crt 的实现了。
       VC++ 的 crt 是创建了一个单独的 heap,叫做 __crtheap ,它对于用户是看不见的,
       但是在 new/malloc 的实现中,都是用 HeapAlloc 在这个 __crtheap 堆上分配的,
       也就是说 malloc(size) 基本上可以认为等同于 HeapAlloc(__crtheap, size)
       (当然实际上 crt 内部还要维护一些内存管理的数据结构,
        所以并不是每次 malloc 都必然会触发 HeapAlloc ),
       这样 new/malloc 就和 windows 的 heap 机制吻合了。
       (这里说的是 VC 的 crt 实现,我不知道其它 crt 实现是否如此)
     
    3. 如果一个进程需要动态库支持,系统在加载 dll 的时候,在 dll 的启动代码 _DllMainCRTStartup 中,
       会创建这个 __crtheap ,所以理论上有多少个 dll,就有多少个 __crtheap 。
       最后主进程的 mainCRTStartup 中还会创建一个为主进程服务的 __crtheap 。
       (由于顺序总是先加载 dll ,然后才启动 main 进程,
        所以你可以看到各个 dll 的 __crtheap 地址比较小,
        而主进程的 __crtheap 地址比较大,当然排在最前面的堆是每个进程的主 heap 。)
     
    4. 从上面的分析中可以看出,对于 crt 来说,由于每个 dll 都有自己的 heap ,
       所以每个 dll 通过 new/malloc 分配的内存都是在自己 dll 内部的那个 heap 上用 HeapAlloc 来分配的,
       而如果你想在其它模块中释放,那么在释放的时候 HeapFree 就会失败了,
       因为各个模块的 __crtheap 是不一样的。
     
    事情基本清楚了,在 windows 下一个进程存在着多个 heap ,
    除了一个主 heap 外,还有很多的 __crtheap ,用来处理通过 C/C++ 的运行库进行的内存操作。
    所以使用 new/malloc 来分配的内存实际上都是局部的,可以在多个 dll 中共享,
    但是却必须是谁申请谁释放。
     
    这个是 Windows 下的一个规则。以前知道这个规则,但是不知道为什么,现在算是比较明白了。
    如果在 dll 内部使用 HeapAlloc(GetProcessHeap(), 0, 字节块大小 ) 来分配的内存,
    是可以在 dll 以外释放的,
    因为这时内存分配在全局的主 heap 上,而不是分配在 dll 自己的 __crtheap 上。
  • 相关阅读:
    em
    How to locate a path?
    云图说 | 揭秘云硬盘高可靠性的秘密,速来围观
    【华为云技术分享】开发团队中的任务没人领取,你头疼吗?
    介绍一种更方便的代理池实现方案
    4行Python代码生成图像验证码
    【华为云技术分享】机器学习(02)——学习资料链接
    【华为云技术分享】华为开发者大会HDC.Cloud带你探索强化学习三大挑战及落地实践
    【华为云技术分享】【一统江湖的大前端(8)】matter.js 经典物理
    华为开发者大会HDC.Cloud硬核技术解读:知识图谱构建流程及方法
  • 原文地址:https://www.cnblogs.com/nuoforever/p/14820633.html
Copyright © 2011-2022 走看看