C++ 卸载DLL时内存泄漏是否会导致主机进程泄漏?
考虑这种情况:C++ 卸载DLL时内存泄漏是否会导致主机进程泄漏?,c++,winapi,dll,memory-management,crt,C++,Winapi,Dll,Memory Management,Crt,考虑这种情况: dll = LoadDLL() dll->do() ... void do() { char *a = malloc(1024); } ... UnloadDLL(dll); 此时,调用malloc()时分配的1k是否会再次用于主机进程? DLL正在静态链接到CRT。不,您没有泄漏 如果混合使用dll模型(静态、动态),那么如果在dll中分配内存、在其他dll中释放内存(或在exe中释放内存),最终可能会出现内存错误 这意味着静态链接的CRT创建的堆与不同dl
dll = LoadDLL()
dll->do()
...
void do() {
char *a = malloc(1024);
}
...
UnloadDLL(dll);
此时,调用malloc()时分配的1k是否会再次用于主机进程?
DLL正在静态链接到CRT。不,您没有泄漏
如果混合使用dll模型(静态、动态),那么如果在dll中分配内存、在其他dll中释放内存(或在exe中释放内存),最终可能会出现内存错误
这意味着静态链接的CRT创建的堆与不同dll的CRT不是同一堆
如果您链接了CRT的动态版本,那么当堆在所有动态链接的CRT之间共享时,就会出现泄漏。这意味着您应该始终将应用程序设计为使用动态CRT,或者确保从不跨dll边界管理内存(即,如果您在dll中分配内存,则始终提供一个例程以在同一dll中释放内存)可以进行测试,查看是否存在内存泄漏。您运行一个简单的测试30次,每次分配1 MB。你应该很快弄明白 有一件事是肯定的。如果您在DLL中分配了内存,您也应该在那里释放内存(在DLL中) 例如,您应该有如下内容(简单但直观的伪代码): 必须这样做,因为DLL的堆与原始进程(加载DLL)的堆不同。来自MSDN CRT库的每个副本都有一个 分离的和不同的状态。像这样的 CRT对象,例如文件句柄, 环境变量和区域设置是 仅对CRT副本有效 这些对象的分配位置或 设置当DLL及其用户使用 CRT库的不同副本, 不能传递这些CRT对象 跨越DLL边界并期望 必须在屏幕上正确拾取它们 另一边 还有,因为每一份CRT 库有自己的堆管理器, 在一个CRT库中分配内存 以及在DLL中传递指针 要由其他对象释放的边界 CRT库的副本是一个潜在的 堆损坏的原因
希望这有帮助。你说不出来。这取决于静态和动态CRT的实现。它甚至可能取决于分配的大小,因为有CRT将大的分配转发给操作系统,但为小的分配实现自己的堆 CRT泄漏的问题当然是它泄漏。不泄漏的CRT的问题是,可执行文件可能合理地期望使用内存,因为malloc’ed内存应该在调用free之前保持可用
编辑-添加链接场景的描述。实际上,标记的答案不正确。就在那里有个漏洞。虽然每个dll实现自己的堆并在关闭时释放它在技术上是可行的,但大多数“运行时”堆(静态或动态)都是围绕Win32 process heap API的包装器
除非有人特别注意保证情况并非如此,否则dll将泄漏每个加载、执行、卸载周期的分配。谢谢!您能否详细说明CRT如何/何时释放其堆存储?这是由编译器/链接器作为某种默认dll退出代码添加的吗?警告:依赖于实现!CRT可以简单地为进程提供对OS堆的访问,在这种情况下,您可以在DLL中分配,并在退出时调用free out.DllMain。我希望它引用计数,直到dll完全卸载,然后移除堆。MSalters是正确的,例如你可以在任何地方分配和释放,但如果你的应用程序崩溃,你会泄漏内存,只有重新启动才能释放内存(例如Win3.1全局堆)
dll = DllLoad();
ptr = dll->alloc();
dll->free(ptr);
DllUnload(dll);