导入的库函数内存会移动吗?库未卸载重载时函数地址是否始终不变?
Windows动态库函数地址相关问题解答
问题1:导入的库函数在内存中是否会被移动?
在Windows系统下,只要动态库(DLL)没有被卸载或重新加载,库中的函数在内存中的位置就不会被移动。
具体来说:
- 当你通过
LoadLibrary加载DLL时,系统会先尝试将它加载到DLL本身指定的「首选基地址」(这个地址是编译DLL时设置的)。如果这个地址没有被进程中的其他模块占用,DLL就直接加载到这里,函数的内存位置就是固定的。 - 如果首选基地址被占用了,系统会自动对DLL进行重定位,把它加载到进程地址空间中的另一个空闲区域。这个重定位操作是在加载阶段完成的,一旦DLL加载完成,它在内存中的位置就完全固定了,不会在程序运行过程中被动态移动。
问题2:假设动态库未被卸载和重载,指向库中函数的函数地址在整个程序执行期间是否会保持不变?
答案是肯定的,只要满足「DLL未被卸载、未被重新加载」这个前提,你通过GetProcAddress获取的函数指针就会始终有效,地址不会发生变化。
看你给出的代码示例:
HMODULE hm = LoadLibrary("SomeLibrary.dll"); SomeFunction fn = (SomeFunction)GetProcAddress(hm, "SomeFunction"); fn(arg1, arg2); // 该fn在整个执行期间是否始终有效?
只要你没有调用FreeLibrary(hm)卸载这个DLL,也没有在模块被卸载后再次调用LoadLibrary("SomeLibrary.dll")(重复加载可能导致模块地址变化,不过同一进程中未卸载时重复加载会返回同一个模块句柄),fn这个函数指针就可以安全地在程序整个生命周期中使用,每次调用都会指向同一个内存地址的函数。
需要额外注意的是:如果DLL被卸载后重新加载,哪怕是同一个DLL,新加载的模块可能会被放到不同的内存地址,这时候之前保存的函数指针就失效了,必须重新调用GetProcAddress获取新的地址。
内容的提问来源于stack exchange,提问作者Joseph Hurti
相关产品推荐
相关产品推荐

