首页 > 系统相关 >Windows 下主程序与动态库(*.dll)释放对方分配的内存操作要点

Windows 下主程序与动态库(*.dll)释放对方分配的内存操作要点

时间:2023-04-21 14:38:05浏览次数:39  
标签:__ 主程序 crtheap Windows malloc dll 内存 heap

同样的代码程序: 主程序中释放了一块在 动态库(*.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 上。

标签:__,主程序,crtheap,Windows,malloc,dll,内存,heap
From: https://www.cnblogs.com/lidabo/p/17340223.html

相关文章

  • Windows10取消首次开机画面
    在首次设置界面,同时按住Ctrl+shift+F3,然后系统会重启,进入桌面后,系统可能会弹出部署模式选项,直接按窗口右上角“X”退出。XCOPY%windir%\System32\svchost.exe%windir%\System32\oobe\audit.exe/X无法找到或打不开用户和组工具又不能通过cmd激活Administrator和修改口令时,我通......
  • ImportError: DLL load failed while importing QtChart: 找不到指定的模块
    这个错误通常是由于您的Python环境缺少QtChart模块或QtChart模块依赖的库文件之一导致的。解决此问题的方法可能因操作系统和Python环境而异,但下面是一些常见的解决方法:检查是否已安装QtChart模块和其依赖项。您可以使用pip命令在终端中安装QtChart模块:Copycodepipinstal......
  • 2022山东省职业院校技能大赛物联网赛项(高职组)windows维护
    任务要求:netsh(NetworkShell)是一个windows系统本身提供的功能强大的网络配置命令行工具,请选手在命令提示符窗口中使用命令将netsh的配置信息导出到c:\interface.txt文件中。在服务器计算机进行配置,指定每个shell的最大内存数量为150MB。完成以上任务后请......
  • 2022全国职业院校技能大赛物联网赛项(高职组)windows维护
    任务要求:在控制台命令行窗口中,使用命令查看网络连接以及每一个网络接口设备状态,将命令和执行后的结果截图,另存为B-2-1.jpg。答: 对服务器计算机配置规则:“禁止工作站计算机访问本机任何程序或者端口,暂不启用此规则”,将配置结果界面截图另存为B-2-2.jpg。答: 在控......
  • 2022全国职业院校技能大赛物联网赛项(中职组)windows维护
    任务要求:   在服务器电脑的C盘创建IOT文件夹,赋予Everyone所有者完全控制权限,将配置截图,另存为D-4-1.jpg。答:将系统的虚拟内存设置为自动管理所有驱动器的分页文件大小的配置界面截图,另存为D-4-2.jpg。答:设置密码最长使用期限50天(非域成员),将配置界面截图,另存为D-4-3.j......
  • 动态库dll编写经验
    流程(1)新建dll工程,空白工程即可(2)编写接口代码(3)添加def文件,用这个最省事def文件说明:LIBRARYgeos-functionEXPORTSisPointInPolygon_GFC#调用c++编写的动态库注意入口函数的大小写,用WinDbg工具查看[DllImport("geos-function.dll",EntryPoint="isPoint......
  • Windows 10 补丁包 msu 转 cab 用 dism 安装
    dism/online/add-package/packagepath:.\Windows6.1-KB2533623-x64.cab/norestart或dism/online/add-package/packagepath:"C:\Users\Administrator\Desktop\pack\Windows6.1-KB2533623-x64.cab"/norestart或dism/online/add-package/packagepat......
  • 由于解决找不到vcruntime140_1.dll,无法继续执行代码重新安装程序可能会解决此问题
    vcruntime140_1.dll是vs2010编译的程序默认的库文件它的丢失易导致游戏、应用软件等程序运行出现错误无法运行打开,致使程序无法正常运行,它的解决办法也是非常简单的,下面小编把vcruntime140_1.dll丢失的详细解决办法分享给大家,亲测有效随便打开一个浏览器在顶部网页输入【dll修复程......
  • 由于找不到 XINPUT1_3.dll,无法继续执行代码。重新安装程序可能会解决此问题。
    ---------------------------EpicGamesLauncher.exe - 系统错误---------------------------由于找不到 XINPUT1_3.dll,无法继续执行代码。重新安装程序可能会解决此问题。 ---------------------------确定   --------------------------- 解决方法:安装最新DirectX。......
  • Windows 与 虚拟机VirtualBox smb共享
    一、安装Samba更新系统:sudoaptupdatesudoaptupgrade安装Samba:sudoaptinstallsamba二、配置共享创建共享目录sudomkdir /samba_share允许用户访问,修改权限:sudochmod777 /samba_share三、配置Samba打开samba配置文件,sudovim /etc/samba/smb.conf按i进......