2

当执行“调用”指令来调用 DLL 导出函数时,它会将 EIP 设置为存储在 DLL 中的函数的地址。如果同时执行的另一个程序,调用属于同一个DLL的同一个函数,跳转地址是否相同?

4

2 回答 2

4

简短的回答是视情况而定

DLL 是按部分组织的,每个部分可以由许多进程共享。通常只有共享代码段(当 DLL 在相同的基地址加载时)并且每个进程都有其私有数据段

DLL 的优点之一是您可以在许多进程之间共享它们的代码(然后您可以节省系统内存,因为系统不会加载它们的许多实例)。当然,数据不能(通常)共享,因此必须为每个实例复制数据。

这意味着通常DLL 代码的内存在不同的进程之间共享,那么它可能具有相同的地址。我说“可能”是因为Virtual Address Space,即使内存是共享的,也不能保证它在每个进程上都具有相同的地址。为了快速测试使用GetProcAddress并多次运行该过程以比较函数地址,您可以使用MSDN中的这个简单程序:

#include <windows.h>
#include <iostream>

void _tmain()
{
    typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);

   SYSTEM_INFO si;
   ZeroMemory(&si, sizeof(SYSTEM_INFO));

   PGNSI fnGetNativeSystemInfo = reinterpret_cast<PGNSI>(GetProcAddress(
       GetModuleHandle(TEXT("kernel32.dll")),  "GetNativeSystemInfo"));

   std::cout << fnGetNativeSystemInfo << std::endl;
}

您应该(通常)看到每个导出函数的相同地址,但您可能看不到。依赖这种行为从来都不是一个好主意。好的,这就是故事,但由于 ASLR,过去几年发生了一些变化,也请看一下这篇文章

如果您必须使用相同的 DLL 在进程之间共享数据,则最好使用一些共享内存,请查看MSDN 上的这篇文章作为示例。

于 2012-05-03T08:36:57.293 回答
1

由于其他程序/进程被映射到它们自己单独的地址空间,我怀疑地址是否相同。

于 2012-05-03T08:34:41.647 回答