【发布时间】:2019-10-12 13:33:47
【问题描述】:
我正在为 Windows 编译一个程序。
我希望它检查系统中是否存在 foo.dll,如果不存在,则打印错误消息并退出。这样做是否安全:
- 将
/DELAYLOAD foo.dll标志传递给链接器; - 在main()的最开始,手动调用
auto handle = LoadLibraryA("foo.dll"),检查handle是否不为NULL; - 如果不为NULL,继续工作;
- 在 main() 结束时,调用 FreeLibrary(handle)?
我想知道是否会由于混合延迟加载和手动调用 LoadLibraryA() 而导致中断。另外,如果有人可以提出一种更简单或更正确的方法来做我想做的事,我将不胜感激。
【问题讨论】:
-
真的可以在解决延迟加载 api(s) 的同时处理错误。如果您使用标准
__delayLoadHelper2(来自 delayimp.lib) - 您可以实现__pfnDliFailureHook2或处理VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND)异常。但是如果你想停止工作,如果 foo.dll 没有找到 - 为什么不正常链接到它,没有延迟加载?您的程序根本无法启动并显示错误 - foo.dll 未找到。如果您想要工作,即使 foo.dll 不存在(或不导出所有 api),使用 delayload 也是有意义的,但是您以某种方式处理这种情况 -
如果您只需要检查 DLL 的存在和版本信息,请致电
LoadLibraryExW(L"foo.dll", NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE)。如果它已经被映射为一个模块,它会增加引用计数并返回对它的引用。否则,它将 DLL 映射为数据段。 -
@RbMm,延迟加载可以让程序有机会通过
SetDefaultDllDirectories和AddDllDirectory修改默认加载程序搜索路径,通过省略PATH和DLL 中的工作目录来提高安全性搜索并让应用程序完全控制在哪里查找其依赖项。 SxS 激活上下文可以实现相同的目标甚至更多,但配置起来要复杂得多。 -
@ErykSun 是的,如果某些 dll 很少,并不总是在正常执行路径中使用,我们可以只在真正需要时才加载它,但不是无条件地加载它。或者,如果某些 api 仅存在于最新版本的 Windows 中,则可以通过延迟加载等方式处理此问题,但如果只想在开始时停止运行应用程序,如果找不到 dll - 更合乎逻辑的已经使用直接导入而不会延迟。当然如果不想做一些工作以防 dll 不存在
-
@RbMm 也许 OP 想要有条件代码:如果可以加载 DLL,则执行一个块,如果无法加载则运行一个块。我相信,您的“以某种方式处理此案”正是 OP 试图建立的。
标签: c++ windows dll linker delayed-execution