DLL内存管理

时间:2010-10-27 08:33:00

标签: c++ c dll memory-management

我对Windows如何管理.dll的内存几乎没有疑问。

  • 当.dll被加载到主机中时 过程,如何管理内存?

  • .dll是否可以访问整个 主机进程可用的内存 或只是其中的一部分?即是 内存是有限制的 由一个函数分配 .dll文件?

  • STL类是否像string,vector(动态) 增加储存量等 dll,在这里没有问题吗?

2 个答案:

答案 0 :(得分:5)

  

.dll是否可以访问整个   主机进程可用的内存   或只是其中的一部分?就是在那里   分配内存时的限制   通过.dll中的函数?

将DLL加载到主机进程后,DLL中的代码“生活”与原始可执行模块中的“生活”代码没有任何区别。对于正在执行的进程,所有内存范围都是相同的,无论它们来自DLL还是来自原始可执行文件。

DLL中的代码可以做什么与原始exec模块中编译的代码可以做什么没有区别。

也就是说,在使用堆时存在差异 - 这些问题在Space_C0wb0y中提供了comments

中的链接
  

STL类是否像字符串,矢量   (动态增加存储)等   由dll使用,工作没有问题   这里吗?

如果您在DLL的界面中使用它们,它们创建问题(可解决的问题,但仍然存在)。如果您不在DLL接口级别使用它们,将不会(或者只应在非常罕见的情况下)创建问题。我相信还有一些更具体的问题和答案。

基本上,如果在接口级别使用它们,则DLL和EXE必须使用“完全”相同的标志进行编译,即类型需要是二进制兼容的。即如果你的DLL中的编译器标志(优化等)与EXE中的那些不同,那么std::string在EXE与DLL的内存中的布局不同,那么在两者之间传递一个字符串对象将导致崩溃或无声错误(或恶魔飞出你的鼻子)。

如果您只使用函数内部的STL类型或DLL内部的函数,那么它们与EXE的兼容性无关紧要。

答案 1 :(得分:5)

“内存管理”通常是一种分裂责任。操作系统将大块地址空间分配给运行时,然后运行时将较小的位交给程序。该地址空间可能有也可能没有分配RAM。 (如果没有,将有交换空间来支持它)

基本上,当加载DLL时,Windows会为代码和数据分段分配地址空间,并调用DllMain()。 C ++编译器将安排从DllMain()调用全局ctors。如果它是用C ++编写的DLL,它可能依赖于C ++运行时DLL,而后者依赖于Kernel32.DLL和User32.DLL。 Windows了解此类依赖关系,并将安排以正确的顺序加载它们。

证明只有一个地址空间,因此DLL可以访问进程的所有内存。如果在两个进程中加载​​DLL,则会有两个代码和数据的逻辑副本。 (代码和只读数据的副本可能共享相同的物理RAM)。

如果DLL使用OS函数分配内存,Windows将把内存分配给DLL进行分配的进程。进程必须返回内存,但进程中的任何代码都可以这样做。如果您的DLL使用C ++函数分配内存,它将通过调用C ++运行时DLL中的operator new来实现。必须通过在(相同的)C ++运行时DLL中调用operator delete来返回该内存。同样,谁做到这一点并不重要。

vector<>这样的STL类可以多次实例化,但只要你使用相同的编译器就没关系。所有实例化都将基本相同,并且所有实例都将向量的内存返回到相同的释放函数。

这个解释有两个主要假设:

  1. EXE及其DLL都使用相同的编译器进行编译
  2. EXE及其DLL都链接到C ++运行时DLL(即不是静态链接)
  3. 如果要发布单个自包含的EXE,则对C ++运行时的静态链接很有用。但是,如果您已经在运送DLL,那么您应该将C ++运行时保留在自己的DLL中。