我对Windows如何管理.dll文件的内存存在一些疑问。
当.dll被加载到宿主进程中时,内存是如何管理的?
.dll是否可以访问宿主进程可用的所有内存,还是只能访问部分内存?也就是说,当函数在.dll内部分配内存时,是否存在限制?
如果.dll使用STL类,例如string、vector(动态增加的存储等),会有问题吗?
我对Windows如何管理.dll文件的内存存在一些疑问。
当.dll被加载到宿主进程中时,内存是如何管理的?
.dll是否可以访问宿主进程可用的所有内存,还是只能访问部分内存?也就是说,当函数在.dll内部分配内存时,是否存在限制?
如果.dll使用STL类,例如string、vector(动态增加的存储等),会有问题吗?
DllMain()
。C++编译器会安排从DllMain()
中调用全局构造函数。如果它是用C++编写的DLL,它很可能依赖于一个C++运行时DLL,而这个DLL又依赖于Kernel32.DLL和User32.DLL。Windows理解这些依赖关系,并会安排它们以正确的顺序加载。operator new
来执行此操作。必须通过在(相同的)C++运行时DLL中调用operator delete
来返回该内存。同样,无论谁这样做都没问题。vector<>
这样的STL类可以被多次实例化,但只要使用相同的编译器就没有关系。所有的实例化都将是基本相等的,并且所有的实例化都会将向量的内存返回给相同的释放函数。_SECURE_SCL
等。 - Martin Ba.dll是否可以访问主进程可用的所有内存或仅部分内存?即,当函数在.dll中分配内存时是否存在限制?
在DLL被加载到主进程后,对于“生活”在DLL中的代码与“生活”在原始可执行模块中的代码,没有任何区别。对于正在执行的进程,所有内存范围都是相同的,无论它们来自DLL还是来自原始可执行文件。
从DLL中获取的代码所能做的事情与编译在原始可执行模块中的代码所能做的事情没有区别。
话虽如此,在使用堆时确实存在差异-这些差异在Space_C0wb0y提供的评论中有解释。
像字符串、向量等STL类(动态增加存储)由.dll使用,这里会有问题吗?
如果在DLL的接口层使用它们,它们将会创建问题(可解决的问题,但仍然存在问题)。如果不在DLL接口层使用它们,则不会(或只在非常罕见的情况下)创建问题。我相信还有更多关于此的具体问题和答案。
基本上,如果在接口层使用它们,则必须使用“完全”相同的标志编译DLL和EXE,即类型需要二进制兼容。也就是说,如果您的DLL中的编译器标志(优化等)与EXE中的标志不同,以至于在EXE和DLL中内存中的std :: string
不同,则在两者之间传递字符串对象将导致崩溃或静默错误(或从您的鼻子飞出的恶魔)。
如果仅在DLL内部函数之间或函数内部使用STL类型,则它们与EXE的兼容性并不重要。