Vik*_*tor 8 c++ dll winapi memory-management crt
考虑这种情况:
dll = LoadDLL()
dll->do()
...
void do() {
char *a = malloc(1024);
}
...
UnloadDLL(dll);
Run Code Online (Sandbox Code Playgroud)
此时,在调用malloc()时分配的1k是否可以再次用于主机进程?DLL静态链接到CRT.
由OS跟踪的进程使用的内存适用于整个进程,而不是特定于DLL.
内存由操作系统以块的形式提供给程序,称为堆
堆管理器(malloc/new等)进一步划分块并将其交给请求代码.
只有在分配了新堆时,操作系统才会检测到内存增加.
当DLL静态链接到C运行时库(CRT)时,将编译具有DLL代码调用的CRT函数的CRT的私有副本并将其放入DLL的二进制文件中.Malloc也包括在内.
只要静态链接的DLL中存在的代码尝试分配内存,就会调用malloc的私有副本.
因此,通过此malloc从OS获取仅对此malloc副本可见的私有堆,并且它分配此私有堆中的代码所请求的内存.
当DLL卸载时,它会卸载它的私有堆,并且当整个堆返回到操作系统时,这个泄漏就会被忽略.
但是,如果动态链接DLL,则内存由malloc的单个共享版本分配,全局到共享模式中链接的所有代码.
由此全局malloc分配的内存来自堆,该堆也是用于在动态aka共享模式中链接的所有其他代码的堆,因此是常见的.因此,来自该堆的任何泄漏都会成为影响整个过程的泄漏.
编辑 - 添加了链接方案的说明.
你不能说.这取决于静态和动态CRT的实现.它甚至可能取决于分配的大小,因为有CRT将大量分配转发给OS,但是为小分配实现自己的堆.
CRT泄漏的问题当然是泄漏.CRT不泄漏的问题是可执行文件可能合理地期望使用内存,因为malloc的内存应该保持可用,直到调用free.
gbj*_*anb -1
不,你不会泄漏。
如果您混合 dll 模型(静态、动态),那么如果您在 dll 中分配内存,然后在另一个 dll 中释放该内存(或在 exe 中释放),则最终可能会出现内存错误
这意味着静态链接 CRT 创建的堆与不同 dll 的 CRT 创建的堆不同。
如果您与 CRT 的动态版本链接,那么就会出现泄漏,因为堆在所有动态链接的 CRT 之间共享。这意味着您应该始终将应用程序设计为使用动态 CRT,或者确保您永远不会跨 dll 边界管理内存(即,如果您在 dll 中分配内存,请始终提供一个例程以在同一 dll 中释放它)