动态负载库和运行时误解的显式链接
Posted
技术标签:
【中文标题】动态负载库和运行时误解的显式链接【英文标题】:Explicit Linking of Dynamic Load Library and Runtime misconception 【发布时间】:2019-03-26 16:07:33 【问题描述】:我在 Windows 中使用 DLL。我创建了其中一个,并且我可以成功地将我的客户端程序链接到 DLL。但我有一个误解。当我阅读 DLL 时,有一句话强调当 DLL 加载到内存中时,所有程序实例都可以使用它。所以它导致我们有效地使用内存并且代码重复从未发生过。
所以我编写了一个程序,它可以成功加载一个 DLL 并使用它。当程序运行时,我在不同的路径中执行了前一个程序的示例,该路径中不存在 DLL,但是当我运行第二个程序时,它显示错误,DLL 不加载。
我的假设是当第一个程序将 DLL 加载到内存中时,它的一个实例存在于内存中,所以我应该再次使用它,但它没有发生。所以我想知道多个程序如何使用一个 DLL 的实例?我应该如何实现一个例子来测试这种行为?程序本身的路径中必须有DLL的样本吗?
对不起,英语不好,我不得不提一下,我是新手程序员,不是专业人士。对不起,如果你发现这个问题太愚蠢了。这是我的代码:
程序.cpp
#include <Windows.h>
#include <iostream>
#include <string>
typedef void(__cdecl *PtrSetInformation)(std::string, std::string, int);
typedef void(__cdecl *PtrShowInformation)(void);
auto main() -> int
HINSTANCE HandlerInstance = LoadLibrary(TEXT("LibEngine.dll"));
if (!HandlerInstance)
std::cout << "DLL doesn't load successfuly." << std::endl;
else
std::cout << "Dll is loaded successfuly." << std::endl;
PtrSetInformation OSetInformation = reinterpret_cast<PtrSetInformation>(GetProcAddress(HandlerInstance, "SetInformation"));
PtrShowInformation OShowInformation = reinterpret_cast<PtrShowInformation>(GetProcAddress(HandlerInstance, "ShowInformation"));
if (!OSetInformation || !OShowInformation)
std::cout << "Function pointers doesn't initiliazed successfuly." << std::endl;
else
OSetInformation("Mikhail", "Razborov", 24);
OShowInformation();
std::cin.get();
return 0;
我的 DLL 代码:
#include <iostream>
#include <string>
std::string __name;
std::string __family;
int __age;
extern "C"
__declspec(dllexport) void __cdecl SetInformation(std::string arg_name, std::string arg_family, int arg_age)
__name = arg_name;
__family = arg_family;
__age = arg_age;
__declspec(dllexport) void __cdecl ShowInformation()
std::cout << "Your name is " << __name << " " << __family << std::endl;
std::cout << "You are a " << __age << " year old programmer." << std::endl;
【问题讨论】:
【参考方案1】:即使 DLL 的内存映像可能是共享的(并非总是如此),Windows 在加载 .exe 时仍需要访问磁盘上的副本。这是因为您可能在不同的目录中有两个同名的不同 DLL,而 Windows 将每个 DLL 视为一个单独的实体。
地址空间布局随机化 (ASLR) 的出现改变了在进程之间共享 DLL 代码的目标。 Raymond Chen 已经在博客中广泛讨论了这一点,例如 here。
【讨论】:
以上是关于动态负载库和运行时误解的显式链接的主要内容,如果未能解决你的问题,请参考以下文章
不运行时接收消息,Xamarin Android上的显式广播和隐式广播